ESP8266 loopt vast

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 12:50

die 11 feb oplossen was eenvoudig: ) nu de rest nog

Advertisement

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 12:51

maar nu eerst wat sociale verplichtingen

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

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 11 Feb 2017, 14:47

Nou de oorzaak lijkt gevonden....
Als ik weer eens wat van die serials aanzet dan blijkt dat hij op enig moment (rond de 20 minuten = 1200000 miliseconden) zegt dat hij niet meer mag verzenden omdat er kennelijk geen puls meer binnenkomt. Nou dat klopt dus. noPowertime = 1200000.
Ik zal hem eens inkorten naar 2 minuten.....

@edit: En inderdaad. Stopt nu na 2 minuten. Dus het programma doet gewoon wat het moet doen..... (op dat dagnummer na dan)
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 16:04

Dat klopt als je het met de parameter waarden draait maar na geruime tijd houdt het echt op. Als ik sendtime terugbreng loopt het programma steevast vast na 237 loops . die 20 minuten is dan nog lang niet voorbij . bovendien zou na een nieuwe puls het programma weer moeten starten. Ik ben er echt nog niet Nico. Groet van een koud terras in Ermelo:)

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

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 11 Feb 2017, 17:21

Ik heb je programma ff geheel herzien. Tevens een simulatie ingebouwd.
cpp code
#include <Arduino.h>
/*
* 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>

#define SIMULATIE // MAAK HIER EEN COMMENT VAN VOOR DE ECHTE SITUATIE

#ifdef SIMULATIE
#include "ESP8266TrueRandom.h" // te downloaden bij https://github.com/marvinroger/ESP8266TrueRandom
#endif
//
// programma constanten
//
const uint32_t SEND_TIME = 1000; // tijd tussen verzenden data TIJDELIJK op 30 seconden
const uint32_t NO_POWER_TIME = 1000 * 60 * 3; // tijdsduur geen pulsen meer ontvangen (normaliter 20 minuten)
#ifdef SIMULATIE
const uint32_t SIMULATIE_TIJD = 50000000; // elke 8 seconden genereren we een puls voor simulatie
uint32_t simulatieTijd; // random puls duur
#endif
//
// Stroom en puls variabelen
//
uint32_t pulseCount = 0; //Number of pulses, used to measure energy.
uint32_t pulseTime; // moment waarop de pulse wordt verwerkt
uint32_t lastTime; // vorige moment waarop de puls is verwerkt

volatile boolean pulse = false; // indicator dat er een puls is geweest
//power and energy
double power; // vermogen dat is geleverd
double opbrengst; // totale opbrengst
// Number of pulses per wh - found or set on the meter.
#ifdef SIMULATIE
uint32_t ppwh = 7; // 1000 pulses/kwh = 1 pulse per wh
#else
uint32_t ppwh = 1; // 1000 pulses/kwh = 1 pulse per wh
#endif
//
// maanden tabel
//
const char monthArray[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
//
// internet specifieke zaken
//
const char* ssid = "xxxxxxxxx";
const char* password = "xxxxxxxxx";
const char* host = "pvoutput.org";
const char* SystemId = "XXXXXXXX";
const char* APIKey = "XXXXXXXXXXXXXXXXXXXX";
uint32_t sent = 0; // tijd tussen verzenden data


//
// timers
//
uint32_t noPowerTimer; // timer die vaststeld hoelang er geen power is
uint32_t sendTimer; // timer die bepaalt wanneer er verzonden wordt
uint32_t simulatieTimer; // timer die de pulsen simuleert

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());

noPowerTimer = millis(); // start de timers
sendTimer = noPowerTimer;

#ifdef SIMULATIE
simulatieTimer = 0;
randomSeed(ESP8266TrueRandom.random());
#endif

// KWH pulsen worden geteld via interrupt
attachInterrupt(2, onPulse, FALLING);
}
/**
* @name loop
* Wordt eindeloos aangeroepen
*/
void loop() {
uint32_t ditMoment = millis(); // nu
char tijdstring[30]; // ontvangst veld van getTime.

uint8_t dag = 0; // dagnummer
uint8_t maand = 0; // maandnummer
uint16_t jaar = 0; // jaartal
uint8_t uur = 0; // uren
uint8_t minuut = 0; // minuten
//
// leg de indeling van de uren en minuten over een 6 byte veld (5 voor de tijd + 1 byte voor de terminator ('\0')
//
union {
struct {
char urenAlsChar[2];
char dubbelePunt;
char minutenAlsChar[2];
char terminator;
};
char tijdAlsCharArray[6];
} tijdIndeling;

//
// check of er een puls is binnengekomen
//
#ifndef SIMULATIE
if (pulse) {
pulse = false; // deze puls is verwerkt
pulseCount++; // verhoog aantal pulsen voor totale opbrengst verwerking
#else
//
// maak een random simulatie tijd om zo de puls frequentie wat te varieren
//

simulatieTijd = random(SIMULATIE_TIJD);

if (ditMoment - simulatieTimer > simulatieTijd){
pulseCount++;
simulatieTimer = ditMoment;
#endif

lastTime = pulseTime; // bewaar vorige puls moment
pulseTime = ditMoment; // zet de huidige tijd vast
//
// Calculate power
//
power = (3600000.0 / double((pulseTime - lastTime))) / (double)ppwh;
//
//Find Wh elapsed
//
opbrengst = (1.0 * (double)pulseCount / (double)(ppwh));
//
// er komt nog steeds stroom binnen dus reset de nopower timer
//
noPowerTimer = ditMoment;
}

//
// kijk of we de limiet van geen stroom nog niet zijn overschreden
//
if (ditMoment - noPowerTimer < NO_POWER_TIME) {
//
// er is op zijn minst binnen de afgelopen 20 minuten NOG stroom geleverd
//
if ((ditMoment - sendTimer) > SEND_TIME) {
//
// eerst het resultaat veilig stellen. Dit omdat de char array in de functie dynamisch is en zo kan verdwijnen
//
strcpy(tijdstring, getTime()); // getTime geeft een pointer terug dus we kunnen die gelijk in de copy slag gebruiken
//
// nu nog ff de uren/minuten zoeken
//
char * pos = strstr(tijdstring, ":"); // we krijgen een char pointer terug waar de eerste : voorkwam in de array

if (pos != NULL) { // en die moet gevuld zijn
//
// nu 2 posities teruggaan en we hebben het begin van de uren
// deze kopieren we in de union tijdIndeling samen met de dubbele punt en minuten
//
pos = pos - 2;
strncpy(tijdIndeling.tijdAlsCharArray, pos, 5);
//
// maak nu van uren en minuten elk een kleine char array
//
tijdIndeling.dubbelePunt = '\0';
tijdIndeling.terminator = '\0';
//
// beide kun je nu converteren in een uint8_t bijv.
//
uur = atoi(tijdIndeling.urenAlsChar);
minuut = atoi(tijdIndeling.minutenAlsChar);
char werkveld[5]; // ff een werkveld om te converteren
strncpy(werkveld, &tijdstring[5], 2); // converteer dag
werkveld[2] = '\0';
dag = atoi(werkveld);

strncpy(werkveld, &tijdstring[8], 3); // converteerd maand
werkveld[3] = '\0';
maand = findMonthIndex(werkveld);

strncpy(werkveld, &tijdstring[12], 4); // converteer jaar
werkveld[4] = '\0';
jaar = atoi(werkveld);
//
// GMT aanpassing
//
uur++;
if (uur == 24) {
uur = 0;
}
//
// We now create a URI for the request
//
char url [200]; // char array om url op te bouwen
char opbrengstStr[10]; // om een float in char array om te zetten
char powerStr[10]; // om een float in char array om te zetten

dtostrf(opbrengst, 7, 2, opbrengstStr); // zet de float om in een 7.2 cijfer
strcpy(opbrengstStr, trimLeadingSpaces(opbrengstStr)); // en haal de voorloop spaties weg

dtostrf(power, 7, 2, powerStr);
strcpy(powerStr, trimLeadingSpaces(powerStr));
//
// bouw de url op
//
sprintf(url, "/service/r2/addstatus.jsp?key=%s&sid=%s&d=%4d%02d%02d&t=%02d:%02d&v1=%s&v2=%s",
APIKey,
SystemId,
jaar,
maand,
dag,
uur,
minuut,
opbrengstStr,
powerStr);
Serial.println(url);
//
// De data verzenden naar onze host
//
//
// //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;
// }

// This will send the request to the server
/* client.print(String("GET ") + url + " HTTP/1.1\r\n" + //TIJDELIJK UITGEZET
"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");
//
// reset de send timer
//
sendTimer = ditMoment;
//
// als er binnen 10 minuten geen pulsen zijn binnengekomen
// dan zetten we het vermogen op 0
//
if ((ditMoment - pulseTime) > 60000) {
power = 0.0; // als er 10 minuten geen pulsen zijn gekomen is power 0
}

} else {
//
// als je hier terecht zou komen dan heb je geen tijdstring ontvangen
//
Serial.println("Geen tijd kunnen vinden");
}
}
} else {
//
// we hebben al meer dan 20 minuten geen power
//
if (uur == 22) {
//
// na 22:00 worden de totalen op 0 gezet
//
pulseCount = 0;
opbrengst = 0.0;
power = 0.0;
}
}
} // einde loop

char * getTime() // functie om tijd op te halen van website
{
char *startPositie; // start positie van datum veld in regel
uint8_t charArrayIndex = 0; // index binnen array
char charArray[200]; // ff ruim genomen buffer voor ontvangen regels
charArray[0] = '\0'; // de regel leegmaken
WiFiClient client;
//
// maak connectie met een server om de tijd te ontvangen
//
while (!client.connect("www.google.com", 80)) {
Serial.println("connection failed, retrying...");
}
client.print("HEAD / HTTP/1.1\r\n\r\n"); // dit zorgt ervoor dat de server de tijd teruggeeft
while (!client.available()) {
yield(); // om de stress op de server te verlichten
}
//
// Als er data is te verwerken
//
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
//
// kijk of dit de datumregel is
//
startPositie = strstr(charArray, "\nDate: ");
//
// is dit is onze regel?
//
if (startPositie != NULL) {
//
// yep dus skip 7 posities en we hebben het startpunt
//
startPositie = startPositie + 7; //was 7
client.stop();
return startPositie;
} else {
// Serial.println(" niet de gewenste regel dus zet hem maar weer op 0 in else");
//
charArray[0] = '\0';
charArrayIndex = 0;
}
} else {
charArrayIndex++;
}
}
Serial.println("De tijd server stuurt niets terug");
client.stop();
startPositie = charArray;
return startPositie; // lege tabel dus geen datum
}
/**
* @name onPulse
* Wordt via een interrupt aangeroepen
*/
void onPulse() {

static uint32_t last_interrupt_time = 0; // moment van laatste interrupt
uint32_t interrupt_time = millis(); // haal de interne millis tijd op

if (interrupt_time - last_interrupt_time > 1500) { //declare the debounce/block out interval in setup
pulse = true;
}

last_interrupt_time = interrupt_time; // en bewaar dit moment voor de volgende puls
}
/**
* @name findMonthIndex
* @param monthChar char array to month name in 3 chars + \0
* @return uint8_t month index
*/
uint8_t findMonthIndex(char * monthChar){
uint8_t month;
//
// zoek door de maanden tabel
//
for (month = 0; month < 12; month++) {
if (strcmp(monthChar, &monthArray[month][0]) == 0) {
//
// gevonden. Dus verder zoeken niet nodig
//
break;
}
}

month++; // 1 erbij optellen omdat we beginnen bij 0 in de tabel
return month;
}
/**
* @name trimLeadingSpaces
* @param charString pointer to string containing chars
* @return new pointer to first non space
*/
char * trimLeadingSpaces(char * charString) {

char *ptr = charString;

for (uint16_t i = 0; i < strlen(charString); i++) {
//
// kijk of het een spatie is
if (*ptr == 0x20 ) {
ptr++;
} else {
//
// we zijn er dus klaar
//
break;
}
}
return ptr;
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 17:48

Thuis gelijk proberen. In de auto leest het lastig op mijn telefoonscherm en 2 jagermeisters tegen de kou. Wordt vervolgd tnx Nico

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

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 11 Feb 2017, 19:15

wacht nog maar ff....
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 19:42

dat doe ik, want er gebeurden dingen die ik niet verwachtte en begreep.

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

Re: ESP8266 loopt vast

Berichtdoor nicoverduin » 11 Feb 2017, 20:33

Ik heb de client static gemaakt. En nu heeft hij ruim een uur gedraaid met 140 gesimuleerde pulsen met gemiddeld 20 verzendingen per puls. Samen goed voor 2800 x ge tijdserver aanroepingen. Tevens de timers goed geprogrammeerd. Anders was hij mogelijk na 49 dagen (timer overflow) misgegaan. Verder eea wat gehershuffeld ed. Kijk maar ff.
De simulator staat ingesteld op een puls van rond de 30 sec. Zenden doe ik elke halve seconde.
Tenslotte nog ff gespeeld met de berekening van power. Heb daar nog wel wat twijfels over. Maar dat kan altijd nog verander worden.
cpp code
#include <Arduino.h>
/*
* 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>

#define SIMULATIE // MAAK HIER EEN COMMENT VAN VOOR DE ECHTE SITUATIE

#ifdef SIMULATIE
#include "ESP8266TrueRandom.h" // te downloaden bij https://github.com/marvinroger/ESP8266TrueRandom
#endif
//
// programma constanten
//
const uint32_t SEND_TIME = 500; // tijd tussen verzenden data TIJDELIJK op 30 seconden
const uint32_t NO_POWER_TIME = 1000 * 60 * 10; // tijdsduur geen pulsen meer ontvangen (normaliter 20 minuten)
#ifdef SIMULATIE
const uint32_t SIMULATIE_TIJD = 30000; // elke 8 seconden genereren we een puls voor simulatie
uint32_t simulatieTijd; // random puls duur
#endif
//
// Stroom en puls variabelen
//
uint32_t pulseCount = 0; //Number of pulses, used to measure energy.
uint32_t pulseTime; // moment waarop de pulse wordt verwerkt
uint32_t lastTime = 0; // vorige moment waarop de puls is verwerkt

volatile boolean pulse = false; // indicator dat er een puls is geweest
//power and energy
double power; // vermogen dat is geleverd
double opbrengst; // totale opbrengst
// Number of pulses per wh - found or set on the meter.
#ifdef SIMULATIE
uint32_t ppwh = 1; // 1000 pulses/kwh = 1 pulse per wh
#else
uint32_t ppwh = 1; // 1000 pulses/kwh = 1 pulse per wh
#endif
//
// maanden tabel
//
const char monthArray[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
//
// internet specifieke zaken
//
const char* ssid = "xxxxxxxxxx";
const char* password = "xxxxxxxxxxx";
const char* host = "pvoutput.org";
const char* SystemId = "XXXXXXXX";
const char* APIKey = "XXXXXXXXXXXXXXXXXXXX";
uint32_t sent = 0; // tijd tussen verzenden data


//
// timers
//
uint32_t noPowerTimer; // timer die vaststeld hoelang er geen power is
uint32_t sendTimer; // timer die bepaalt wanneer er verzonden wordt
uint32_t simulatieTimer; // timer die de pulsen simuleert

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());

noPowerTimer = millis(); // start de timers
sendTimer = noPowerTimer;

#ifdef SIMULATIE
simulatieTimer = 0;
randomSeed(ESP8266TrueRandom.random());
#endif

// KWH pulsen worden geteld via interrupt
attachInterrupt(2, onPulse, FALLING);
}
/**
* @name loop
* Wordt eindeloos aangeroepen
*/
void loop() {
uint32_t ditMoment = millis(); // nu
char tijdstring[30]; // ontvangst veld van getTime.

uint8_t dag = 0; // dagnummer
uint8_t maand = 0; // maandnummer
uint16_t jaar = 0; // jaartal
uint8_t uur = 0; // uren
uint8_t minuut = 0; // minuten
//
// leg de indeling van de uren en minuten over een 6 byte veld (5 voor de tijd + 1 byte voor de terminator ('\0')
//
union {
struct {
char urenAlsChar[2];
char dubbelePunt;
char minutenAlsChar[2];
char terminator;
};
char tijdAlsCharArray[6];
} tijdIndeling;

//
// check of er een puls is binnengekomen
//
#ifndef SIMULATIE
if (pulse) {
pulse = false; // deze puls is verwerkt
pulseCount++; // verhoog aantal pulsen voor totale opbrengst verwerking
#else
//
// maak een random simulatie tijd om zo de puls frequentie wat te varieren
//


if (ditMoment - simulatieTimer > simulatieTijd){
pulseCount++;
simulatieTijd = random((SIMULATIE_TIJD - 8000), SIMULATIE_TIJD);
simulatieTimer = ditMoment;
#endif

//
// Calculate power
//
if (lastTime != 0){
//
// tonen vanaf de 2e puls
//
// power = (3600000.0 / double((pulseTime - lastTime))) / (double)ppwh;
power = (3600000 / (double((pulseTime - lastTime)))) * (double)ppwh;
Serial.print(" pulsetime: ");
Serial.print(pulseTime);
Serial.print(" lastTime: ");
Serial.print(lastTime);
Serial.print(" power: ");
Serial.print(power);
Serial.print(" pulseCnt: ");
Serial.println(pulseCount);
//
//Find Wh elapsed
//
opbrengst = (1.0 * (double)pulseCount / (double)(ppwh));
}
//
// er komt nog steeds stroom binnen dus reset de nopower timer
//
noPowerTimer = ditMoment;
lastTime = pulseTime; // bewaar vorige puls moment
pulseTime = ditMoment; // zet de huidige tijd vast
}

//
// kijk of we de limiet van geen stroom nog niet zijn overschreden
//
if (ditMoment - noPowerTimer < NO_POWER_TIME) {
//
// er is op zijn minst binnen de afgelopen 20 minuten NOG stroom geleverd
//
if ((ditMoment - sendTimer) > SEND_TIME) {
//
// eerst het resultaat veilig stellen. Dit omdat de char array in de functie dynamisch is en zo kan verdwijnen
//
strcpy(tijdstring, getTime()); // getTime geeft een pointer terug dus we kunnen die gelijk in de copy slag gebruiken
//
// nu nog ff de uren/minuten zoeken
//
char * pos = strstr(tijdstring, ":"); // we krijgen een char pointer terug waar de eerste : voorkwam in de array

if (pos != NULL) { // en die moet gevuld zijn
//
// nu 2 posities teruggaan en we hebben het begin van de uren
// deze kopieren we in de union tijdIndeling samen met de dubbele punt en minuten
//
pos = pos - 2;
strncpy(tijdIndeling.tijdAlsCharArray, pos, 5);
//
// maak nu van uren en minuten elk een kleine char array
//
tijdIndeling.dubbelePunt = '\0';
tijdIndeling.terminator = '\0';
//
// beide kun je nu converteren in een uint8_t bijv.
//
uur = atoi(tijdIndeling.urenAlsChar);
minuut = atoi(tijdIndeling.minutenAlsChar);
char werkveld[5]; // ff een werkveld om te converteren
strncpy(werkveld, &tijdstring[5], 2); // converteer dag
werkveld[2] = '\0';
dag = atoi(werkveld);

strncpy(werkveld, &tijdstring[8], 3); // converteerd maand
werkveld[3] = '\0';
maand = findMonthIndex(werkveld);

strncpy(werkveld, &tijdstring[12], 4); // converteer jaar
werkveld[4] = '\0';
jaar = atoi(werkveld);
//
// GMT aanpassing
//
uur++;
if (uur == 24) {
uur = 0;
}
//
// We now create a URI for the request
//
char url [200]; // char array om url op te bouwen
char opbrengstStr[10]; // om een float in char array om te zetten
char powerStr[10]; // om een float in char array om te zetten

dtostrf(opbrengst, 7, 2, opbrengstStr); // zet de float om in een 7.2 cijfer
strcpy(opbrengstStr, trimLeadingSpaces(opbrengstStr)); // en haal de voorloop spaties weg

dtostrf(power, 7, 2, powerStr);
strcpy(powerStr, trimLeadingSpaces(powerStr));
//
// bouw de url op
//
sprintf(url, "/service/r2/addstatus.jsp?key=%s&sid=%s&d=%4d%02d%02d&t=%02d:%02d&v1=%s&v2=%s",
APIKey,
SystemId,
jaar,
maand,
dag,
uur,
minuut,
opbrengstStr,
powerStr);
Serial.println(url);
//
// De data verzenden naar onze host
//
//
// //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;
// }

// This will send the request to the server
/* client.print(String("GET ") + url + " HTTP/1.1\r\n" + //TIJDELIJK UITGEZET
"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");
//
// reset de send timer
//
sendTimer = ditMoment;
//
// als er binnen 10 minuten geen pulsen zijn binnengekomen
// dan zetten we het vermogen op 0
//
if ((ditMoment - pulseTime) > 60000) {
power = 0.0; // als er 10 minuten geen pulsen zijn gekomen is power 0
}

} else {
//
// als je hier terecht zou komen dan heb je geen tijdstring ontvangen
//
Serial.println("Geen tijd kunnen vinden");
}
}
} else {
//
// we hebben al meer dan 20 minuten geen power
//
if (uur == 22) {
//
// na 22:00 worden de totalen op 0 gezet
//
pulseCount = 0;
opbrengst = 0.0;
power = 0.0;
}
}
} // einde loop

char * getTime() // functie om tijd op te halen van website
{
char *startPositie; // start positie van datum veld in regel
uint8_t charArrayIndex = 0; // index binnen array
char charArray[200]; // ff ruim genomen buffer voor ontvangen regels
charArray[0] = '\0'; // de regel leegmaken
static WiFiClient client;
//
// maak connectie met een server om de tijd te ontvangen
//
while (!client.connect("www.google.com", 80)) {
Serial.println("connection failed, retrying...");
}
client.print("HEAD / HTTP/1.1\r\n\r\n"); // dit zorgt ervoor dat de server de tijd teruggeeft
while (!client.available()) {
yield(); // om de stress op de server te verlichten
}
//
// Als er data is te verwerken
//
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
//
// kijk of dit de datumregel is
//
startPositie = strstr(charArray, "\nDate: ");
//
// is dit is onze regel?
//
if (startPositie != NULL) {
//
// yep dus skip 7 posities en we hebben het startpunt
//
startPositie = startPositie + 7; //was 7
client.stop();
return startPositie;
} else {
// Serial.println(" niet de gewenste regel dus zet hem maar weer op 0 in else");
//
charArray[0] = '\0';
charArrayIndex = 0;
}
} else {
charArrayIndex++;
}
}
Serial.println("De tijd server stuurt niets terug");
client.stop();
startPositie = charArray;
return startPositie; // lege tabel dus geen datum
}
/**
* @name onPulse
* Wordt via een interrupt aangeroepen
*/
void onPulse() {

static uint32_t last_interrupt_time = 0; // moment van laatste interrupt
uint32_t interrupt_time = millis(); // haal de interne millis tijd op

if (interrupt_time - last_interrupt_time > 1500) { //declare the debounce/block out interval in setup
pulse = true;
}

last_interrupt_time = interrupt_time; // en bewaar dit moment voor de volgende puls
}
/**
* @name findMonthIndex
* @param monthChar char array to month name in 3 chars + \0
* @return uint8_t month index
*/
uint8_t findMonthIndex(char * monthChar){
uint8_t month;
//
// zoek door de maanden tabel
//
for (month = 0; month < 12; month++) {
if (strcmp(monthChar, &monthArray[month][0]) == 0) {
//
// gevonden. Dus verder zoeken niet nodig
//
break;
}
}

month++; // 1 erbij optellen omdat we beginnen bij 0 in de tabel
return month;
}
/**
* @name trimLeadingSpaces
* @param charString pointer to string containing chars
* @return new pointer to first non space
*/
char * trimLeadingSpaces(char * charString) {

char *ptr = charString;

for (uint16_t i = 0; i < strlen(charString); i++) {
//
// kijk of het een spatie is
if (*ptr == 0x20 ) {
ptr++;
} else {
//
// we zijn er dus klaar
//
break;
}
}
return ptr;
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: ESP8266 loopt vast

Berichtdoor René » 11 Feb 2017, 21:36

Oh dear,

je slaat wel heel erg veel lessen over Nico.
Dat van die debug regels is heel leuk. Maar er zijn een paar dingen die ik niet snap. Ik kopieer de code nog een keer en schrijf daar mijn reactie in rood. Rood lijkt niet te werken dus maar XXXXXXXXXXXXX Eigenlijk snap ik niet dat de code wil compileren.
Code: Alles selecteren
#include <Arduino.h>
/*
 *  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>
 
#define SIMULATIE                                   // MAAK HIER EEN COMMENT VAN VOOR DE ECHTE SITUATIE
 
#ifdef SIMULATIE
#include "ESP8266TrueRandom.h"                      // te downloaden bij <!-- m --><a class="postlink" href="https://github.com/marvinroger/ESP8266TrueRandom">https://github.com/marvinroger/ESP8266TrueRandom</a><!-- m -->
#endif
//
// programma constanten
//
const uint32_t SEND_TIME        = 500;          // tijd tussen verzenden data TIJDELIJK op 30 seconden
const uint32_t NO_POWER_TIME    = 1000 * 60 * 10;   // tijdsduur geen pulsen meer ontvangen (normaliter 20 minuten)
#ifdef SIMULATIE
const uint32_t SIMULATIE_TIJD   = 30000;            // elke 8 seconden genereren we een puls voor simulatie
uint32_t simulatieTijd;                             // random puls duur
#endif
//
// Stroom en puls variabelen
//
uint32_t pulseCount = 0;                            //Number of pulses, used to measure energy.
uint32_t pulseTime;                                 // moment waarop de pulse wordt verwerkt
uint32_t lastTime = 0;                              // vorige moment waarop de puls is verwerkt
 
volatile boolean pulse = false;                     // indicator dat er een puls is geweest
//power and energy
double power;                                       // vermogen dat is geleverd
double opbrengst;                                   // totale opbrengst
                                                    // Number of pulses per wh - found or set on the meter.
#ifdef SIMULATIE
uint32_t ppwh = 1;                                  // 1000 pulses/kwh = 1 pulse per wh
#else
uint32_t ppwh = 1;                                  // 1000 pulses/kwh = 1 pulse per wh
#endif
//
// maanden tabel
//
const char  monthArray[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
//
// internet specifieke zaken
//
const char* ssid        = "xxxxxxxxxx";
const char* password    = "xxxxxxxxxxx";
const char* host        = "pvoutput.org";
const char* SystemId    = "XXXXXXXX";
const char* APIKey      = "XXXXXXXXXXXXXXXXXXXX";
uint32_t sent   = 0;                                // tijd tussen verzenden data
 
 
//
// timers
//
uint32_t        noPowerTimer;       // timer die vaststeld hoelang er geen power is
uint32_t        sendTimer;          // timer die bepaalt wanneer er verzonden wordt
uint32_t        simulatieTimer;     // timer die de pulsen simuleert
 
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());
 
    noPowerTimer    = millis();                     // start de timers
    sendTimer       = noPowerTimer;
 
#ifdef SIMULATIE
    simulatieTimer  = 0;
    randomSeed(ESP8266TrueRandom.random());
#endif
 
    // KWH pulsen worden geteld via interrupt
    attachInterrupt(2, onPulse, FALLING);
}
/**
 * @name loop
 * Wordt eindeloos aangeroepen
 */
void loop() {[color=#FF0000] // waar is de afsluitende accolade van de loop?[/color]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    uint32_t ditMoment = millis();              // nu
    char tijdstring[30];                        // ontvangst veld van getTime.
 
    uint8_t dag     = 0;                        // dagnummer
    uint8_t maand   = 0;                        // maandnummer
    uint16_t jaar   = 0;                        // jaartal
    uint8_t uur     = 0;                        // uren
    uint8_t minuut  = 0;                        // minuten
    //
    // leg de indeling van de uren en minuten over een 6 byte veld (5 voor de tijd + 1 byte voor de terminator ('\0')
    //
    union {
        struct {
            char urenAlsChar[2];
            char dubbelePunt;
            char minutenAlsChar[2];
            char terminator;
        };
        char tijdAlsCharArray[6];
    } tijdIndeling;
 
    //
    // check of er een puls is binnengekomen
    //
#ifndef SIMULATIE
    if (pulse) {    //deze accolade wordt bij mij afgeslopen bij einde loop regel verder op[/color]XXXXXXXXX[/color]XXXXXXXXXXXXXXXX
        pulse       = false;                    // deze puls is verwerkt
        pulseCount++;       [color=#FF0000]//mis ik hie geen "}"    [/color]     XXXXXXXXXXXX[color=#FF0000]XXXXXXXXXXX[/color]XXXXXXXXXXXXXXXXXXXX
#else
    //
    // maak een random simulatie tijd om zo de puls frequentie wat te varieren
    //
 
 
    if (ditMoment - simulatieTimer > simulatieTijd){
        pulseCount++;
        simulatieTijd = random((SIMULATIE_TIJD - 8000), SIMULATIE_TIJD);
        simulatieTimer = ditMoment;
#endif
 
        //
        // Calculate power
        //
        if (lastTime != 0){
            //
            // tonen vanaf de 2e puls
            //
    //      power       = (3600000.0 / double((pulseTime - lastTime))) / (double)ppwh;
            power       = (3600000 / (double((pulseTime - lastTime)))) * (double)ppwh;
            Serial.print(" pulsetime: ");
            Serial.print(pulseTime);
            Serial.print(" lastTime: ");
            Serial.print(lastTime);
            Serial.print(" power: ");
            Serial.print(power);
            Serial.print(" pulseCnt: ");
            Serial.println(pulseCount);
            //
            //Find Wh elapsed
            //
            opbrengst   = (1.0 * (double)pulseCount / (double)(ppwh));
        }
        //
        // er komt nog steeds stroom binnen dus reset de nopower timer
        //
        noPowerTimer = ditMoment;
        lastTime    = pulseTime;                // bewaar vorige puls moment
        pulseTime   = ditMoment;                // zet de huidige tijd vast
    }
 
    //
    // kijk of we de limiet van geen stroom nog niet zijn overschreden
    //
    if (ditMoment - noPowerTimer < NO_POWER_TIME) {
        //
        // er is op zijn minst binnen de afgelopen 20 minuten NOG stroom geleverd
        //
        if ((ditMoment - sendTimer) > SEND_TIME) {
            //
            // eerst het resultaat veilig stellen. Dit omdat de char array in de functie dynamisch is en zo kan verdwijnen
            //
            strcpy(tijdstring, getTime());              // getTime geeft een pointer terug dus we kunnen die gelijk in de copy slag gebruiken
            //
            // nu nog ff de uren/minuten zoeken
            //
            char * pos = strstr(tijdstring, ":"); // we krijgen een char pointer terug waar de eerste : voorkwam in de array
 
            if (pos != NULL) {                        // en die moet gevuld zijn
                //
                // nu 2 posities teruggaan en we hebben het begin van de uren
                // deze kopieren we in de union tijdIndeling samen met de dubbele punt en minuten
                //
                pos = pos - 2;
                strncpy(tijdIndeling.tijdAlsCharArray, pos, 5);
                //
                // maak nu van uren en minuten elk een kleine char array
                //
                tijdIndeling.dubbelePunt = '\0';
                tijdIndeling.terminator = '\0';
                //
                // beide kun je nu converteren in een uint8_t bijv.
                //
                uur     = atoi(tijdIndeling.urenAlsChar);
                minuut  = atoi(tijdIndeling.minutenAlsChar);
                char werkveld[5];                               // ff een werkveld om te converteren
                strncpy(werkveld, &tijdstring[5], 2);           // converteer dag
                werkveld[2] = '\0';
                dag = atoi(werkveld);
 
                strncpy(werkveld, &tijdstring[8], 3);           // converteerd maand
                werkveld[3] = '\0';
                maand = findMonthIndex(werkveld);
 
                strncpy(werkveld, &tijdstring[12], 4);          // converteer jaar
                werkveld[4] = '\0';
                jaar = atoi(werkveld);
                //
                // GMT aanpassing
                //
                uur++;
                if (uur == 24) {
                    uur = 0;
                }
                //
                // We now create a URI for the request
                //
                char url [200];                 // char array om url op te bouwen
                char opbrengstStr[10];          // om een float in char array om te zetten
                char powerStr[10];              // om een float in char array om te zetten
 
                dtostrf(opbrengst, 7, 2, opbrengstStr);                 // zet de float om in een 7.2 cijfer
                strcpy(opbrengstStr, trimLeadingSpaces(opbrengstStr));  // en haal de voorloop spaties weg
 
                dtostrf(power, 7, 2, powerStr);
                strcpy(powerStr, trimLeadingSpaces(powerStr));
                //
                // bouw de url op
                //
                sprintf(url, "/service/r2/addstatus.jsp?key=%s&sid=%s&d=%4d%02d%02d&t=%02d:%02d&v1=%s&v2=%s",
                                                            APIKey,
                                                            SystemId,
                                                            jaar,
                                                            maand,
                                                            dag,
                                                            uur,
                                                            minuut,
                                                            opbrengstStr,
                                                            powerStr);
                Serial.println(url);
                //
                // De data verzenden naar onze host
                //
    //
    //          //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;
    //          }
 
                // This will send the request to the server
                /*       client.print(String("GET ") + url + " HTTP/1.1\r\n" + //TIJDELIJK UITGEZET
                 "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");
                //
                // reset de send timer
                //
                sendTimer = ditMoment;
                //
                // als er binnen 10 minuten geen pulsen zijn binnengekomen
                // dan zetten we het vermogen op 0
                //
                if ((ditMoment - pulseTime) > 60000) {
                    power = 0.0; // als er 10 minuten geen pulsen zijn gekomen is power 0
                }
 
            } else {
                //
                // als je hier terecht zou komen dan heb je geen tijdstring ontvangen
                //
                Serial.println("Geen tijd kunnen vinden");
            }
        }
    } else {
        //
        // we hebben al meer dan 20 minuten geen power
        //
        if (uur == 22) {
            //
            // na 22:00 worden de totalen op 0 gezet
            //
            pulseCount  = 0;
            opbrengst   = 0.0;
            power       = 0.0;
        }
    }
} // einde loop
 
char * getTime()                                // functie om tijd op te halen van website
{
    char        *startPositie;                  // start positie van datum veld in regel
    uint8_t     charArrayIndex = 0;             // index binnen array
    char        charArray[200];                 // ff ruim genomen buffer voor ontvangen regels
    charArray[0] = '\0';                        // de regel leegmaken
    static WiFiClient client;
    //
    // maak connectie met een server om de tijd te ontvangen
    //
    while (!client.connect("www.google.com", 80)) {
        Serial.println("connection failed, retrying...");
    }
    client.print("HEAD / HTTP/1.1\r\n\r\n");    // dit zorgt ervoor dat de server de tijd teruggeeft
    while (!client.available()) {
        yield();                                // om de stress op de server te verlichten
    }
    //
    // Als er data is te verwerken
    //
    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
            //
            // kijk of dit de datumregel is
            //
            startPositie = strstr(charArray, "\nDate: ");
            //
            // is dit is onze regel?
            //
            if (startPositie != NULL) {
                //
                // yep dus skip 7 posities en we hebben het startpunt
                //
                startPositie = startPositie + 7; //was 7
                client.stop();
                return startPositie;
            } else {
                // Serial.println(" niet de gewenste regel dus zet hem maar weer op 0 in else");
                //
                charArray[0] = '\0';
                charArrayIndex = 0;
            }
        } else {
            charArrayIndex++;
        }
    }
    Serial.println("De tijd server stuurt niets terug");
    client.stop();
    startPositie = charArray;
    return startPositie;                                        // lege tabel dus geen datum
}
/**
 * @name onPulse
 * Wordt via een interrupt aangeroepen
 */
void onPulse() {
 
    static uint32_t last_interrupt_time = 0;                // moment van laatste interrupt
    uint32_t interrupt_time     = millis();                 // haal de interne millis tijd op
 
    if (interrupt_time - last_interrupt_time > 1500) {       //declare the debounce/block out interval in setup
        pulse = true;
    }
 
    last_interrupt_time = interrupt_time;                   // en bewaar dit moment voor de volgende puls
}
/**
 * @name findMonthIndex
 * @param monthChar char array to month name in 3 chars + \0
 * @return uint8_t month index
 */
uint8_t findMonthIndex(char * monthChar){
    uint8_t month;
    //
    // zoek door de maanden tabel
    //
    for (month = 0; month < 12; month++) {
        if (strcmp(monthChar, &monthArray[month][0]) == 0) {
            //
            // gevonden. Dus verder zoeken niet nodig
            //
            break;
        }
    }
 
    month++;                        // 1 erbij optellen omdat we beginnen bij 0 in de tabel
    return month;
}
/**
 * @name trimLeadingSpaces
 * @param charString pointer to string containing chars
 * @return new pointer to first non space
 */
char * trimLeadingSpaces(char * charString) {
 
    char *ptr = charString;
 
    for (uint16_t i = 0; i < strlen(charString); i++) {
        //
        // kijk of het een spatie is
        if (*ptr == 0x20 ) {
            ptr++;
        } else {
            //
            // we zijn er dus klaar
            //
            break;
        }
    }
    return ptr;
}


En dan verder: simuleren is mooi en wat je gedaan hebt snap ik een beetje.
Maar als ik de simulatie uit zet en mijn tellertje weer in de "echte loop" zet ipv de Serial.println(url); loopt de boel weer vast. nu niet meer na precies 237 maar een beetje daar om heen.
Laatst gewijzigd door René op 11 Feb 2017, 22:15, in totaal 1 keer gewijzigd.

VorigeVolgende

Terug naar ESP Software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 8 gasten