Read analog frequently and maintain MQTT connection

Hello,

I’m trying to read the blinking LED on my electricity meter and publish it on Home Assistant using MQTT but the problem is that command to update MQTT and maintain connection takes to long so I will miss a blink now and then.

I have a Arduino Pro Mini 3,3v connected to a ESP8266 ESP 01.
There is also a fotoresistor connected on A1.

When the LED on the electricity meter flashes the signal on A1 is above 650 for about 30 milliseconds.
Otherwise it is below 200.

I use PubSubClient.h to connect to MQTT and I need to run client.loop(); once every 10 seconds to maintain connection.
The problem is that it seems to take 172-300 milliseconds.

If I try to use timer interrupts to read analog signal Arduino looses connection to ESP8266.
I’m using SoftwareSerial.h which also uses interrupts so it probably takes too long to read analog and connection with ESP8266 is then lost.

Has anyone suggestions on what I should do?

I’m thinking maybe timer interrupts to read analog would work if I use native RX/TX pins for ESP8266?

Or should I use another Arduino to read analog and communicate with I2C?

Any other suggestions?

#include "WiFiEsp.h"
#include <PubSubClient.h>
#include "SoftwareSerial.h"

// Emulate Serial1 on pins 10/11 if not present
#ifndef HAVE_HWSERIAL1

SoftwareSerial Serial1(10, 11); // RX, TX
#endif

char ssid[] = "WifiName";
char pass[] = "WifiPassword";
int status = WL_IDLE_STATUS;
int reqCount = 0;

String mqtt_id = "Arduino101";
#define mqtt_server "10.10.10.10"
#define mqtt_port 1883
#define mqtt_user "arduino"
#define mqtt_password "Password"


WiFiEspClient espClient;
PubSubClient client;

unsigned long currentMillis = 0;
unsigned long previousMillisMQTT = 0;
unsigned long previousMillisPublish = 0;
unsigned long previousMillisAnalogRead = 0;
unsigned long previousTwoMin = 0;
unsigned long previousOneDay = 0;
unsigned long lastTimeReconnect = 0;

int delayMQTTloop = 10000;
int delayAnalogRead = 3;
bool publishLast = false;
int whatToPublish = 0;
int delayReconect = 5000;

unsigned long blinkTwoMin = 0;
unsigned long blinkTwoMinLast = 0;
unsigned long blinkOneDay = 0;
unsigned long blinkOneDayLast = 0;
int elconsump = 0;
int elconsumday = 0;

int sensorPin = A1;
int sensorValue = 0;
int sensorValueThreshold = 650;
bool sensorValueReadOnce = false;
char somethingToPublish = 0;

int milliseachloop = 0;

void setup()
{

  
  // initialize serial for debugging
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(9600);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  Serial.println("You're connected to the network");
  printWifiStatus();

  client.setClient(espClient);
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  delay(100);
  reconnect();
}

void callback(char* topic, byte* payload, unsigned int length) {
}

void printWifiStatus()
{
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void reconnect()
{
  Serial.print("Attempting MQTT connection...");
  if (client.connect("ESP8266Client2", mqtt_user, mqtt_password)) {
    Serial.println("connected");
  }
  else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
  }
}

void loop()

{
  //Set the time
  currentMillis = millis();

  //Check if time to read analog/blink sensor. Read every 3 milliseconds
  if ((unsigned long)(currentMillis - previousMillisAnalogRead) >= delayAnalogRead) {
    sensorValue = analogRead(sensorPin);
    previousMillisAnalogRead = currentMillis;
    //Räkna upp 1 gång per topp
    if (sensorValue >= sensorValueThreshold && sensorValueReadOnce) {
      sensorValueReadOnce = false;
      blinkTwoMin = blinkTwoMin + 1;
      blinkOneDay = blinkOneDay + 1;
      Serial.print("Sensor:");
      Serial.println(sensorValue);
    }
    else {
      if (sensorValue < sensorValueThreshold - 50) {
        sensorValueReadOnce = true;
      }
    }
  }
  //Calculate electricity consumption every 2 minutes
  if ((unsigned long)(currentMillis - previousTwoMin) >= 120000) {
    previousTwoMin = currentMillis;
    blinkTwoMinLast = blinkTwoMin;
    blinkTwoMin = 0;
    elconsump = blinkTwoMinLast * 15;
    somethingToPublish = 2;
  }
  //Calculate daily electricity consumption
  if ((unsigned long)(currentMillis - previousOneDay) >= 86400000) {
    previousOneDay = currentMillis;
    blinkOneDayLast = blinkOneDay;
    blinkOneDay = 0;
    elconsumday = blinkOneDayLast / 2000;
    somethingToPublish = 1;
  }


  //Check if time to run MQTT loop
  if ((unsigned long)(currentMillis - previousMillisMQTT) >= delayMQTTloop) {
    if (!client.connected() && (unsigned long)(currentMillis - lastTimeReconnect) >= delayReconect) {
      lastTimeReconnect = currentMillis;
      reconnect();
    }
    else {
      client.loop();
      previousMillisMQTT = currentMillis;
    }
  }
  
  //Check if something should be published
  if (somethingToPublish > 0) {

    //Check if MQTT connected
    if (!client.connected() && (unsigned long)(currentMillis - lastTimeReconnect) >= delayReconect) {
      lastTimeReconnect = currentMillis;
      reconnect();
    }
    else {

      //Publish daily consumption in kWh
      if (somethingToPublish == 1) {
        client.publish("Day_consumption2", String(elconsumday).c_str(), true);
        somethingToPublish = 0;
      }

      //Publish current (2 min average) electricity consumption
      if (somethingToPublish == 2) {
        client.publish("Current_El_Consumption2", String(elconsump).c_str(), true);
        somethingToPublish = 0;
      }

    }
  }

  milliseachloop = millis() - currentMillis;
  if (milliseachloop >= 100) {
    Serial.print("Warning, time to complete loop:");
    Serial.println(milliseachloop);
  }

}

Hello,

This problem is now solved and I decided to connect the ESP8266 on native TX/RX pins.
SoftwareSerial.h library is too sensitive for interrupts.
With native TX/RX pins interrupts works perfect, even with analogRead().

One great thing I realized with WiFiEsp.h library is that you can turn off all logging in a file called debug.h.
Otherwise the library was writing info about the connection on the serial port like "Connecting to Wifiname" etc which messed up the the normal communication with AT commands.

Great News. You might want to edit your original title and include the string [SOLVED] in it so other who may stumble upon this thread know there is a solution waiting...