So for me, this is clearly n issue with the internal functions.
Here is my code. It has been working stable for a week. If I replace the delay with yield, it fails after seconds:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#define min(a,b) ((a)<(b)?(a):(b))
const char *ssid = "myssid";
const char *password = "mywifipw";
const char *mqtt_server = "192.168.2.6";
const char *mqtt_user = "powermeter";
const char *mqtt_pw = "mymosquittow";
const char *mqtt_state_topic = "home-le/consumption/power";
unsigned long mqttReconnectTime = millis();
unsigned long mqttReconnectInterval = 5000;
const int analogInPin = A0;
const int ledPin = BUILTIN_LED;
unsigned int threshold = 208;
int thresholdbins[30];
unsigned int thresholdcount = 0;
boolean calibrated = false;
unsigned int sensorValue = 0;
unsigned int valueCount = 0;
float meanSensorValue = 0.;
float lastValue = 0.;
float beforeLastValue = 0.;
unsigned long dispTime = millis();
unsigned int dispInterval = 100;
unsigned long ledTime = millis();
unsigned int ledInterval = 500;
unsigned long lastCountTime = millis();
unsigned int lastCountInterval = 3000;
float powerCons = 0;
WiFiClient espClient;
PubSubClient mqttclient(espClient);
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite ( ledPin, LOW );
Serial.begin ( 115200 );
WiFi.begin ( ssid, password );
Serial.println ( "" );
// Wait for connection
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
Serial.println ( "" );
Serial.print ( "Connected to " );
Serial.println ( ssid );
Serial.print ( "IP address: " );
Serial.println ( WiFi.localIP() );
if ( MDNS.begin ( "powermeter" ) ) {
Serial.println ( "MDNS responder started" );
}
mqttclient.setServer(mqtt_server, 1883);
mqttclient.setCallback(mqtt_callback);
digitalWrite ( ledPin, HIGH );
}
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
}
void loop() {
delay(2);
sensorValue += analogRead(analogInPin);
valueCount++;
if (!mqttclient.connected()) {
if (millis() - mqttReconnectTime > mqttReconnectInterval) {
mqtt_reconnect();
mqttReconnectTime = millis();
}
}
else {
mqttclient.loop();
}
if (millis() - ledTime > ledInterval)
{
digitalWrite ( ledPin, HIGH );
}
if (millis() - dispTime > dispInterval)
{
meanSensorValue = (float)sensorValue / valueCount;
int readval = 190;
if ( meanSensorValue > threshold && lastValue > threshold && beforeLastValue < threshold && (millis() - lastCountTime) > lastCountInterval )
{
powerCons = 48000. / (millis() - lastCountTime);
lastCountTime = millis();
if (mqttclient.connected()) {
char outputStr[5];
sprintf(outputStr, "%d", (int)(powerCons * 1000));
if (calibrated)
mqttclient.publish(mqtt_state_topic, outputStr, true);
Serial.print("Published ");
Serial.println(outputStr);
}
readval = 210;
digitalWrite ( ledPin, LOW );
ledTime = millis();
}
// Serial.print(min(220,meanSensorValue));
// Serial.print(" ");
// Serial.print(210);
// Serial.print(" ");
// Serial.print(readval);
// Serial.print(" ");
// Serial.println(190);
binning_compute(meanSensorValue);
beforeLastValue = lastValue;
lastValue = meanSensorValue;
valueCount = 0;
sensorValue = 0;
dispTime = millis();
}
}
void mqtt_reconnect() {
// Loop until we're reconnected
if (!mqttclient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttclient.connect("powermeter", mqtt_user, mqtt_pw)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(mqttclient.state());
Serial.println(" try again in 5 seconds");
}
}
}
void binning_compute(float sensorval) {
thresholdcount++;
unsigned int bin = (int)sensorval - threshold + 15;
if (bin >= 0 && bin < 30) {
thresholdbins[bin] = thresholdbins[bin] + 1;
}
if (thresholdcount == 9000) {
print_thresholdbins();
threshold = threshold - 15 + binning_findmin();
calibrated = true;
Serial.print("New threshold: ");
Serial.println(threshold);
thresholdcount = 0;
binning_start();
}
}
void binning_start() {
memset(thresholdbins, 0, 30 * sizeof(thresholdbins[0]));
}
int binning_findmin() {
unsigned int maxpos_s = 0;
unsigned int maxpos_e = 29;
while (maxpos_s < 29 && thresholdbins[maxpos_s] <= thresholdbins[maxpos_s + 1]) {
maxpos_s++;
}
Serial.print("Max_s: ");
Serial.println(maxpos_s);
while (maxpos_e > 0 && thresholdbins[maxpos_e] <= thresholdbins[maxpos_e - 1]) {
maxpos_e--;
}
Serial.print("Max_e: ");
Serial.println(maxpos_e);
if (maxpos_e == maxpos_s) {
return 15;
}
unsigned int minpos = (maxpos_s + maxpos_e) / 2;
if (minpos < 1 || minpos > 28) {
return 15;
}
int direct = ((thresholdbins[minpos] - thresholdbins[minpos + 1]) >= 0) ? 1 : -1;
while ((thresholdbins[minpos] - thresholdbins[minpos + direct]) > 0) {
minpos = minpos + direct;
Serial.print(direct);
Serial.print(" ");
Serial.print(thresholdbins[minpos]);
Serial.print(" ");
Serial.print(thresholdbins[minpos + direct]);
Serial.print(" ");
Serial.print(thresholdbins[minpos] - thresholdbins[minpos + direct]);
Serial.print(" minpos: ");
Serial.println(minpos);
}
if (thresholdbins[minpos] == 0) {
int zerocount = 1;
while (thresholdbins[minpos + direct * zerocount] == 0) {
zerocount++;
}
minpos = minpos + direct * (zerocount / 2);
}
Serial.print("minpos_z: ");
Serial.println(minpos);
return minpos;
}
void print_thresholdbins() {
for (int i = 0; i < 29; i++) {
Serial.print(thresholdbins[i]);
Serial.print(" ");
}
Serial.println(thresholdbins[29]);
}