ESP8266 program pauses during WiFi http request

Hello,

Not been on the forum for a long time as ive been out of this for some time but really missed it so decided to get stuck in again!

Im putting together a home energy efficiency monitor and have built up each part seperatly and am now pulling them together, specifcailly these parts are;

  • Interrupt pins based energy meter pulse counting

  • One Wire temperature sensors

  • Local displays

  • HTTP request via wifi to get information into cloud, currently "AskSensors" but their web UI is not the best so moving that, but for now it works for testing.

By in large building things up in modules has worked well and im starting to pull all the elements together. Its also my first venture into programming ESP based devices, always been UNOs and MEGAs etc.

The problem im having is the main loop appearing to pause when i do the HTTP string and WiFi transmission. Ive put a good amount of functions into, well, functions to "keep the loop clean" and ive added some delay to allow the ESP background process to work. Also first time ive had to declare functions before the main loop but looks to be pretty common. Annoying needing to scroll past them all the time.

The interrupts do still count, however serial print, display outputs etc all pause for several seconds on a regularity which ties in with the HTTP requests. Oddly, this doesn't happen on an Uno with ethernet shield, so im thinking its some aspect of the ESP which i don't understand.

The code as below just now simply puts seconds (derived from millis) and also program run time from micros to the LED display and also serial port. In both of these cases, the main loop timer doesnt show as being slow, it just doesnt update.

Link to video showing behaviour, the top display is seconds and bottom is main loop "progTime" and both updated at 2Hz.

Long and short / TLDR point: Core functions work, just sluggishly - any pointers would be appreciated.

The code (with keys, passwords etc hidden with x's);

[code]
/* Energy Meter   serial 115200

   R0
   Reads pulse input and generates a total kWh count and also power.
   Power is based on the internal Millis timer.   For low power times, if we dont get a pulse after a period, then we start to decrement the power.
       This function is to avoid extended periods of time displaying a power value which is no longer current.

   R1
   Added HTTP posting to AskSensors account.   Everything worked except the energyCountPtr, thats not posting anything.   Its OK, thinking to migrate to ThingSpeak.
   Also noticed the low power timeout happens too quickly

   R2
   Not sure what happened, this got stuck to an example

   R2.1
   ESPWiFi - not sure if this was tested, think so.

   R2.2
   Added OTA and merged energy elements from HeatExchanger_logger R3.2
   Cant test OTA from work laptop due to blocked python
   Cant get past watchdog

   R2.3
   Rebuild to find watchdog issue

   R2.4
   Issue was with LCD library so commented out for now to check other things but it otherwise appears working.

   R2.5
   Added MAX72xx 7 segment displays for power & energy

*/

#include <Esp.h>



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************* WiFi HEADER  ******************* //


// includes
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

#include <ESP8266mDNS.h>  // added with OTA
#include <WiFiUdp.h>  // added with OTA
#include <ArduinoOTA.h>  // added with OTA

// Wifi config
const char* wifi_ssid = "gxxxxxxxxy";             // SSID
const char* wifi_password = "oxxxxxxxxx6";         // WIFI
const unsigned int writeInterval = 2000;   // write interval (in ms)

WiFiClientSecure client;

int statusTx = 0;  //transmission status



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************* ASK SENSORS HEADER  ******************* //

// ASKSENSORS config.
String https_host = "api.asksensors.com"; // ASKSENSORS API host name
const int https_port = 443;                        // https port
const char* https_fingerprint =  "xxxxxxxxxx";     // ASKSENSORS HTTPS SHA1 certificate
char* apiBoiler = "xxxxxxxxxxxx";      // Boiler / Garrage API
char* apiEnergy = "xxxxxxxxxxxxxx";      // Energy API   // new API 16/01/2023
String url;
String line;

int updatePeriod = 5;// number of 1Hz loops between transmissions
int periods = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************* LCD DISPLAY  ******************* //

// include the library code:
//#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
//const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 10, d7 = 11;
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************* LED 7 SEGMENT MAX72xx DISPLAY  ******************* //

//from LCDemo7Segmentx16_R2
#include "LedController.hpp"


#define DIN 15 // GPIO15 D1 board D10_SS
#define CS 13  // GPIO13 1 board D11_MOSI
#define CLK 14 // GPIO14 D1 board D13_SCK
const unsigned int NUMBER_OF_DIGITS = 8;
/*
   A single MAX72XX so the Dimensions are 1,1.
   Two in a chain becomes 1,2
   not sure what the first digit is for...?
*/
LedController<1, 2> lc;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************* TIMERS  ******************* //

unsigned long currentMicros = 0;
unsigned long currentMillis = 0;

//2Hz / 500ms loop
unsigned long prevMillis2Hz = 0;
unsigned long millisPer2Hz = 500; // 500ms

//1Hz / 1000ms loop
unsigned long prevMillis1Hz = 0;
unsigned long millisPer1Hz = 1000; // 1000ms

// program timer
int progTime = 0;
int timeEnd = 0;
int loopDelay = 50;  // delay in main loop to allow background processes

//display timer
unsigned long delaytime=500;
unsigned long delayprint=100;

///////////////////////////////////////////////////////
//******************* SYSTEM I/O ******************* //
const int led = 12;



// Outputs(12): 16,15,14,13,12,10,5,4,3,2,1,0
// Inputs(9): 14,13,12,10,5,4,3,2,0
// crash-inducing(5): 11,9,8,7,6

/////////////////////////////////////////////////////////////////
//******************* ELECTRICITY METERING ******************* //

// Set GPIOs for  elecPulse Sensor
const int elecPulseInput = 5;   //GPIO5 = D15/SCL/D3 input

//elecPower & Energy
long elecPulseCount = 0;
unsigned long elecPulseTime, elecLastTime;
double elecPower, elecElapsedkWh = 0;
double elecPowerIn = 0;
double elecPowerDec = 0;
int elecppkwh = 3200; // elecPulsess/kwh
double elecppwh = 0;
int LPtimeout = 10; // timout in Millis is MillisPer2Hz x by this value


/*

  for 3200elecPulses/kWh, load vs time between elecPulses
  Load W | time between (s)
  10    112.5
  20    56.25
  40    28.125
  60    18.75
  80    14.0625
  100   11.25
  150   7.5
  200   5.625
  250   4.5
  300   3.75
  400   2.8125
  500   2.25
  600   1.875
  700   1.607142857
  800   1.40625
  900   1.25
  1000  1.125
  1100  1.022727273
  1200  0.9375
  1300  0.865384615
  1400  0.803571429
  1500  0.75

*/

double elecPowerCal = 0.927; //  correction multiplier for elecPower reading

int energyCountLim = 600; //number of loops to take a total at
int energyCountPtr = 0; //current pointer
double energyAtCount = 0; //current energy at the count
int updated = 0;  // flag to indicate the update has haelecppened



/////////////////////////////////////////////////////////
//******************* GAS METERING ******************* //

// Set GPIOs gaspulse Sensor
const int gasPulseInput = 3;

//Power & Energy
long gasPulseCount = 0;
unsigned long gasPulseTime, gasLastTime;
double gasPower, gasElapsedkWh = 0;
double gasPowerIn = 0;
double GasPpowerDec = 0;

int gasLPtimeout = 10; // timout in Millis is MillisPer2Hz x by this value

float gasCor = 1.02264; // gas correction factor for temperature & pressure
float gasCals = 38.0;  // calorific value

int ppCuM = 100;  // pulse = 0.01cubicM   -  pulses from the meter per cubic meter of gas
float kWhCuM = 0;    // calcualte in setup
float gasppkWh = 0;  // calcualte in setup
double gasPowerCal = 1; //  correction multiplier for power reading


int gasEnergyCountLim = 600; //number of loops to take a total at
int gasEnergyCountPtr = 0; //current pointer
double gasEnergyAtCount = 0; //current energy at the count
int gasUpdated = 0;  // flag to indicate the update has happened






//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////  //////////////////////////////////////////////////////
//******************* FUNCTIONS ******************* //  //******************* FUNCTIONS ******************* //
//////////////////////////////////////////////////////  //////////////////////////////////////////////////////

// not sure why some dont work unless its at the start - very annoying


/////////////////////////////////////////////////////////////////
//******************* electricity pulse countring> ******************* //
// Copied to EnergyMeter R2.2 //

ICACHE_RAM_ATTR void onElecPulse()
{
  //used to measure time between elecPulses.
  elecLastTime = elecPulseTime;
  elecPulseTime = micros();

  //elecPulseCounter
  elecPulseCount++;

  //Find kwh elapsed
  elecElapsedkWh = (1.0 * elecPulseCount / (elecppkwh)); //multiply by 1000 to convert elecPulses per wh to kwh, leave here, only update when elecPulse detected
}


/////////////////////////////////////////////////////////////////
//******************* gas pulse counting> ******************* //
// Copied to EnergyMeter R2.2 //

ICACHE_RAM_ATTR void onGasPulse()
{
  //used to measure time between pulses.
  gasLastTime = gasPulseTime;
  gasPulseTime = micros();

  //pulseCounter
  gasPulseCount++;

  //Find kwh elapsed
  gasElapsedkWh = (1.0 * gasPulseCount / gasppkWh); //multiply by 1000 to convert pulses per wh to kwh, leave here, only update when pulse detected
}


///////////////////////////////////////////////////////////////////////
//******************* Ask Sensors URL Generation ******************* //
// Taken from HeatExchanger_logger_R3.2 //

String asksensorsURL(char* api, String mod, float dat)

{
  /* Create a URL for the request
     assumption is the https_host will be the same/global but the api key, module and data will be variable.
     function retruns the string to be transmitted so the usage is;
     client.print(asksensorsURL([api key], [module name], [floating point data]))
  */

  String furl;

  if (!client.connect(https_host, https_port)) {  // this needs to be here for some reason, if its removed then nothing transmits
    Serial.println("-> connection failed");
  }

  furl = "/write/";
  furl += api;
  furl += "?";
  furl += mod;  //"?module1=";
  furl += "=";
  furl += dat; // random(10, 100);

  return (String("GET ") + furl + " HTTP/1.1\r\n" + "Host: " + https_host + "\r\n" + "Connection: close\r\n\r\n");

}



///////////////////////////////////////////////////////////////////////
//***************** LED 7 SEGMENT MAX72xx DISPLAY ***************** //


//This function can display a float on a 7-Segment display.
//It assumes the dismension of the Ledlcler is <1,row> and the row can be selected with the second parameter.
//The third parameter is used to specify how many digits you want to after the decimal Place.
//The fourth paramether is an offset moving all digits to the left by the specified amount

void displayFloat(float value, unsigned int row = 0, unsigned int decimalPlaces = 1,unsigned int digitOffset = 0){
  unsigned int total_length = NUMBER_OF_DIGITS;
  if(NUMBER_OF_DIGITS<decimalPlaces){return;};

  if(value < 0){
    lc.setChar(row,total_length-1+digitOffset,'-',false);
    total_length--;
  };

  for(unsigned int i = 0; i < decimalPlaces; i ++){
    value*=10.0f;
  }

  unsigned int v = (unsigned int) (value < 0 ? -value : value);

  for (unsigned int i = 0; i < total_length;i++){
    lc.setDigit(row,i+digitOffset,v%10,i == decimalPlaces);
    v/=10;
  }

}


// this sends chars, probably needs fanned out to permit a string to be handed over
void write7SegmentChar(int disp) {

  lc.setChar(disp, 7, '1', false); //left most
  lc.setChar(disp, 6, '.', false);
  lc.setChar(disp, 5, '3', false);
  lc.setChar(disp, 4, '4', false);
  lc.setChar(disp, 3, '.', false);
  lc.setChar(disp, 2, '6', false);
  lc.setChar(disp, 1, '7', false);
  lc.setChar(disp, 0, '8', false);  //right most
}



// this sends chars, probably needs fanned out to permit a string to be handed over
void write7SegmentDigit(int disp) {

  lc.setDigit(disp, 7, 1, false); //left most
  lc.setDigit(disp, 6, 2, false);
  lc.setDigit(disp, 5, 3, false);
  lc.setDigit(disp, 4, 4, false);
  lc.setDigit(disp, 3, 5, false);
  lc.setDigit(disp, 2, 6, false);
  lc.setDigit(disp, 1, 7, false);
  lc.setDigit(disp, 0, 8, false);  //right most
}

/*
  This method will scroll all the hexa-decimal
  numbers and letters on the display. You will need at least
  four 7-Segment digits. otherwise it won't really look that good.
*/
void scrollDigits() {
  for (int i = 0; i < 13; i++) {
    lc.setDigit(0, 7, i + 1, false); //left most
    lc.setDigit(0, 6, i + 2, false);
    lc.setDigit(0, 5, i + 3, false);
    lc.setDigit(0, 4, i + 4, false);
    lc.setDigit(0, 3, i + 5, false);
    lc.setDigit(0, 2, i + 6, false);
    lc.setDigit(0, 1, i + 7, false);
    lc.setDigit(0, 0, i + 8, false); //right most
//    delay(delaytime);
  }
  lc.clearMatrix();
//  delay(delaytime);
}

/*
 This method will display the characters for the
 word "Arduino" one after the other on digit 0.
 */
void writeArduinoOn7Segment() {

  // Display 0 (first in line to the arduino)
  lc.setIntensity(0);
  lc.setChar(0,7,'A',false);
  delay(delayprint);
  
  lc.setIntensity(2);
  lc.setRow(0,6,0x05);
  delay(delayprint);

  lc.setIntensity(4);
  lc.setChar(0,5,'d',false);
  delay(delayprint);

  lc.setIntensity(6);
  lc.setRow(0,4,0x1c);
  delay(delayprint);

  lc.setIntensity(8);
  lc.setRow(0,3,B00010000);
  delay(delayprint);

  lc.setIntensity(10);
  lc.setRow(0,2,0x15);
  delay(delayprint);

  lc.setIntensity(12);
  lc.setRow(0,1,0x1D);
  delay(delayprint);

  lc.setIntensity(14);
  lc.setChar(0,0,'1',false);
  delay(delayprint);

  // Display 01 (first in line to the arduino)
  lc.setIntensity(0);
  lc.setChar(1,7,'A',false);
  delay(delayprint);
  
  lc.setIntensity(2);
  lc.setRow(1,6,0x05);
  delay(delayprint);

  lc.setIntensity(4);
  lc.setChar(1,5,'d',false);
  delay(delayprint);

  lc.setIntensity(6);
  lc.setRow(1,4,0x1c);
  delay(delayprint);

  lc.setIntensity(8);
  lc.setRow(1,3,B00010000);
  delay(delayprint);

  lc.setIntensity(10);
  lc.setRow(1,2,0x15);
  delay(delayprint);

  lc.setIntensity(12);
  lc.setRow(1,1,0x1D);
  delay(delayprint);

  lc.setIntensity(14);
  lc.setChar(1,0,'2',false);
  delay(delayprint);

  
  delay(delaytime);
  lc.clearMatrix();

}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {

  /////////////////////////////////////////////////////////
  //******************* SERIAL SETUP ******************* //

  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  delay(500); // let serial settle etc

  Serial.print("wdtEnable... > ");
  ESP.wdtEnable(5000);
  Serial.println("... done wdtEnable");

  /////////////////////////////////////////////////////////
  //******************* LCD SETUP ******************* //

  // Serial.print("lcd.begin... > ");
  //  lcd.begin(16, 2);
  // Print a message to the LCD.
  //  lcd.print("hello, world!");
  //  Serial.println("... done lcd.beginLCD");



  ////////////////////////////////////////////////////////////
  //*********** LED 7 SEGMENT MAX72xx DISPLAY  *********** //


  //Here a new Ledlcler object is created without hardware SPI.
  lc = LedController<1, 2>(DIN, CLK, CS);

  /* Set the brightness to a medium values, can change in the main loop */
  lc.setIntensity(8);
  /* and clear the display */
  lc.clearMatrix();




  ////////////////////////////////////////////////////////////
  //******************* RUN ONCE CALCS  ******************* //
  Serial.print("run one calcs... > ");
  elecppwh = elecppkwh / 1000;   // pulses per kwh converted to pulses per wh

  kWhCuM = (gasCor * gasCals) / 3.6 ; // energy per cubicM of gas.
  gasppkWh = kWhCuM / ppCuM; // number of pulses per kWh of gas
  Serial.println("... done run one calcs.");

  //////////////////////////////////////////////////////
  //******************* I/O SETUP ******************* //
  Serial.print("I/O setup... > ");
  pinMode(elecPulseInput, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(elecPulseInput), onElecPulse, RISING);

  // pinMode(gasPulseInput, INPUT_PULLUP);
  //  attachInterrupt(digitalPinToInterrupt(gasPulseInput), onGasPulse, RISING);

  // Set LED to LOW
  // pinMode(led, OUTPUT);
  //digitalWrite(led, LOW);
  Serial.print("... done IO setup...");


  Serial.println("... and fed the watchdog.");

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //******************* WiFi SETUP  ******************* //

  Serial.print("********** connecting to WIFI : ");
  Serial.println(wifi_ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("-> WiFi connected");
  Serial.println("-> IP address: ");
  Serial.println(WiFi.localIP());
  // Set Client to insecure
  client.setInsecure();



  /*
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //******************* ARDUINO OTA SETUP  ******************* //
    // lifted out of the "BasicOTA" example which worked when applying flashing LEDs update
   // not tested fully in this code base *****

    // Port defaults to 8266
    // ArduinoOTA.setPort(8266);

    // Hostname defaults to esp8266-[ChipID]
    // ArduinoOTA.setHostname("myesp8266");

    // No authentication by default
    // ArduinoOTA.setPassword("admin");

    // Password can be set with it's md5 value as well
    // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
    // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

    ArduinoOTA.onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH) {
        type = "sketch";
      } else { // U_FS
        type = "filesystem";
      }

      // NOTE: if updating FS this would be the place to unmount FS using FS.end()
      Serial.println("Start updating " + type);
    });
    ArduinoOTA.onEnd([]() {
      Serial.println("\nEnd");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) {
        Serial.println("Auth Failed");
      } else if (error == OTA_BEGIN_ERROR) {
        Serial.println("Begin Failed");
      } else if (error == OTA_CONNECT_ERROR) {
        Serial.println("Connect Failed");
      } else if (error == OTA_RECEIVE_ERROR) {
        Serial.println("Receive Failed");
      } else if (error == OTA_END_ERROR) {
        Serial.println("End Failed");
      }
    });
    ArduinoOTA.begin();
    Serial.println("Ready");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

  */

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //******************* SERIAL PRINT HEADERS  ******************* //

  Serial.print("currentMillis");
  Serial.print(",");
  Serial.print("progTime");
  Serial.print(",");

  Serial.print("elecPowerInterrupt");
  Serial.print(",");
  Serial.print("elecPower");
  Serial.print(",");
  Serial.print("elecElapsedkWh");
  Serial.print(",");

  /*  Serial.print("htgFlow");
    Serial.print(",");
    Serial.print("htgReturn");
    Serial.print(",");
    Serial.print("flueIntake");
    Serial.print(",");
    Serial.print("flueExhaust");
  */
  Serial.println();
writeArduinoOn7Segment();
}  // END OF SETUP





//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //******************* TIMER CONTROLS  ******************* //
  delay(loopDelay);
  
  currentMillis = millis();  // use the same Millis for all timing each loop, i.e. dont end up with many Millisses, apart from...
  currentMicros = micros();  // where we use micros to do the program time
  progTime = currentMicros - timeEnd;  // will use the current micros at the end of the loop
  

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //******************* 2Hz TIMER LOOP  ******************* //


  if ((currentMillis - prevMillis2Hz) >= millisPer2Hz)
  {
    prevMillis2Hz = currentMillis;

    //Serial.print("PrevMillis1Hz:");
    Serial.println(prevMillis1Hz);



    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //***************** LED 7 SEGMENT MAX72xx DISPLAY ***************** //


  lc.setIntensity(15);  

 // float sec = float(millis())/1000;
  
//  displayFloat(sec,0,2);
//  displayFloat(float(progTime),1,0);
  
  displayFloat(float(elecPower),0,2);
  displayFloat(float(elecElapsedkWh),1,3);


    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //******************* ELECTRICAL LCD DISPLAY  ******************* //

    /*
        lcd.setCursor(0, 0);
        lcd.print("W: ");
        lcd.setCursor(3, 0);
        lcd.print(elecPower, 1);

        if (elecPower < 10)
        {
          lcd.print("   "); //3 spaces
        }
        else if (elecPower < 100)
        {
          lcd.print("  "); //2 spaces
        }

        else if (elecPower < 1000)
        {
          lcd.print("  "); //2 spaces
        }

        else
        {
          lcd.print(" "); //1 space
        }

        lcd.setCursor(0, 1);
        lcd.print("kWh: ");
        lcd.setCursor(5, 1);

        lcd.print(elecElapsedkWh, 4);

        if (statusTx == 0)
        {
          // do nothing
        }

        if (statusTx == 1)
        {
          lcd.setCursor(12, 0);
          lcd.print("  Tx");

          statusTx = 0;
        }


        if (statusTx == 2)
        {
          lcd.setCursor(12, 0);
          lcd.print("Fail");

          statusTx = 0;
        }
    */
  }

  //******************* 2Hz TIMER LOOP  ******************* //
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////








  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //******************* 1Hz TIMER LOOP  ******************* //


  if ((currentMillis - prevMillis1Hz) >= millisPer1Hz)
  {
    prevMillis1Hz = currentMillis;
    periods = periods + 1;




    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //******************* ELECTRCICITY METERING  ******************* //

    elecPowerIn = (3600000000.0 / (elecPulseTime - elecLastTime)) / elecppwh; // only updates on interrupt


    elecPower = elecPowerIn * elecPowerCal;

    if (elecPower >= 30000)
    {
      elecPower = 30000;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //******************* SERIAL OUTPUTS  ******************* //

    //Print the values.
    Serial.print(currentMillis);
    Serial.print(",");

    Serial.print(progTime);
    Serial.print(",");
    Serial.print(elecPowerIn);
    Serial.print(",");
    Serial.print(elecPower, 1);
    Serial.print(",");
    Serial.println(elecElapsedkWh, 4);

  }
  //******************* 1Hz TIMER LOOP  ******************* //
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



  /////////////////////////////////////////////////////////////////////////////////
  //******************* ASK SENSORS TRANSMISSION LOOP <HEAD> ******************* //

  if (periods >= updatePeriod)
  {
    periods = 0;
    String tx;

    tx = (asksensorsURL(apiEnergy, "module1", elecPower));  // transmit value in watts
    client.print(tx);
    //Serial.println(tx);

    tx = (asksensorsURL(apiEnergy, "module2", elecPulseCount));
    client.print(tx);
    //Serial.println(tx);

    tx = (asksensorsURL(apiEnergy, "module3", elecElapsedkWh));
    client.print(tx);
    //Serial.println(tx);

    tx = (asksensorsURL(apiEnergy, "module4", gasPulseCount));
    client.print(tx);
    //Serial.println(tx);

    //******************* ASK SENSORS TRANSMISSION LOOP <TAIL> ******************* //
    /////////////////////////////////////////////////////////////////////////////////

  }

  timeEnd = micros(); // program timer will use current micros

}  // End of main loop


[/code]

For reference, using;
AZ-Delivery "D1 Board Nodemcu ESP8266Mod-12f WiFi WLAN module compatible with Arduino"
Programming in either Visual Studio Code or in Arduino 1.8.19 (and also uploading to board).

I obviously can't reproduce your system, but IMHO as far as I can see there are two things that came out to my attention while peeking around your code on http requests.

First:

  if (!client.connect(https_host, https_port)) {  // this needs to be here for some reason, if its removed then nothing transmits
    Serial.println("-> connection failed");
  }

That's fine, and the reason is you need to be connected to send data.:wink: Anyway, if connection fails, better return a null/empty string, and send the request only if not empty, something like this:

...
  if (!client.connect(https_host, https_port)) {  // this needs to be here for some reason, if its removed then nothing transmits
    Serial.println("-> connection failed");
    return "";
  }
...
    tx = (asksensorsURL(apiEnergy, "module1", elecPower));  // transmit value in watts
    if (tx.length() > 0) client.print(tx);

Second:

  return (String("GET ") + furl + " HTTP/1.1\r\n" + "Host: " + https_host + "\r\n" + "Connection: close\r\n\r\n");

This request header "Connection: close" you added asks the server to close the connection after returning you the response data. It means that when you perform client.print(tx); you send the data and then the server will close the connection, so each call to asksensorsURL() will re-establish the connection. And as you're using https I suppose it's a bit more slow than http due to handshakes.

So, I suggest you to use http if you can, and then establish the connection once (inside the if (periods >= updatePeriod) block), perform the GET requests without the "Connection: close" header, and after the last client.print(tx) empty client buffer (GET command implies an answer, but IMHO you should check if it's 200 OK or something else...) and at the end disconnect from the server.
Also check what the server replies to GET requests, I hope it won't reply much other than 200 OK.

As an additional note, if you just need to send a command, if it's a RESTful service better use PUT.

1 Like

@docdoc many, many thanks for taking the time to have a look through the code and give some great feedback.

I implemented the changes one at a time so i moved the client connect to inside the updatePeriod if statement - this made the biggest single difference, the delay was reduced from 4-5 seconds to ~400msec at most.

Appreciably some of your comments are to guard for failures.

Im happy to call that a success for now! I will next change to HTTP as i dont see theres any need for HTTPS given its content, possible AskSensors only supports HTTPS - not currently critical as i used it for speed being something i had used before.

Thanks again and best wishes,
Stuart

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.