Mkr wifi 1010 loop speed improvement plan

https://learn.sparkfun.com/tutorials/smart-home-expansion-kit-for-arduino-101/experiment-9-using-a-current-sensor

Unlike the link, I used mkr wifi 1010, sct-013-000. The rest of the configuration is the same.

The nocktime (t1-t2) being measured now is about 1290m/s, which is too long. I want to reduce this.

The sketches used are as follows.

#include "EmonLib.h"
EnergyMonitor emon1;

double Total = 0;
int count = 0;
double TotalPower = 0;
unsigned long t1 = 0;

void setup() {
  Serial.begin(9600);
  emon1.current(1, 111.1);

  for (int i = 0; i < 5; i++) {
    double IrmsNock = emon1.calcIrms(1480);
    if (IrmsNock < 0.2) {
      Total += IrmsNock;
      count++;
    }
  }

  Total /= count;
  Serial.print("Average IrmsNock: ");
  Serial.println(Total);

  t1 = millis();
}

void loop() {
  unsigned long t2 = millis();
  int nocktime = t2 - t1;
  t1 = t2;

  double Irms = emon1.calcIrms(1480) - Total;
  Irms = (Irms < 0) ? 0 : Irms;

  double power = Irms * 220.0;
  TotalPower += power * nocktime / 3600.0;

  Serial.print(nocktime);
  Serial.print("   Current: ");
  Serial.print(Irms, 4);
  Serial.print(" (A)   Power: ");
  Serial.print(power, 4);
  Serial.print(" (W)   Accumulated Power: ");
  Serial.print(TotalPower / 1000, 4);
  Serial.println(" (W)");
}

Q1. How to reduce nocktime

Don't use 1000 samples :wink: emon1.calcIrms() takes time because the analogRead()s take time; I do not know how fast analogRead() is on your board.

Please use code tags when posting code as described in How to get the best out of this forum.

Hello! Are you saying to reduce the number of samples?
Or do you want me to read it through analogread() and turn it into a current value?

That one.

You can do some testing how long an analogRead() takes. Something in the line of

void setup()
{
  Serial.begin(115200);
  while(!Serial);
  Serial.println("analogRead() speed test");
}

void loop()
{
  uint32_t sum = 0;
  uint32_t startTime = millis();
  for(uint16_t cnt=0; uint16_t <100; cnt++)
  {
    sum += analogRead(A0);
  }
  Serial.println("Average analogRead() time = ");
  Serial.println((millis() - startTime) / 100);
  Serial.print("Average value = ");
  Serial.println(sum/100);
}

Although sum is not strictly necessary, using it in a print statement prevents the compiler from optimising it away.

Not compiled, not tested.

On AVR based boards, an analogRead() takes roughly 100 microseconds; I know that a Due is a lot faster (can't remember how much).

Run the test to get a feel for the speed of analogRead().
And look at what calcIrms() in the EmonLib exactly does.

AnalogRead has a speed of about 1ms. I have a question here. How can I measure the power using analogRead()? The value of analogRead() has not changed.

That is very slow; there must be something wrong with your testing. As said, an AVR does a single analogRead() in approximately 100 microseconds and I expect your board to be a lot faster.

I do not understand. I did not say that you had to use analogRead(); I just needed you to understand where the slowness of your code comes from.

Did you have a look at what calcIrms() does? It simply uses analogRead().

double EnergyMonitor::calcIrms(unsigned int Number_of_Samples)
{

  #if defined emonTxV3
    int SupplyVoltage=3300;
  #else
    int SupplyVoltage = readVcc();
  #endif


  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
    sampleI = analogRead(inPinI);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
    filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum
    sumI += sqI;
  }

  double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
  Irms = I_RATIO * sqrt(sumI / Number_of_Samples);

  //Reset accumulators
  sumI = 0;
  //--------------------------------------------------------------------------------------

  return Irms;
}

According to the processor datasheet, the processor on your board can achieve 350 ks/s, so roughly 3 microseconds for a sample.

I do not know the processor on your board. You can change the resolution using analogReadResolution() - Arduino Reference; a lower resolution should speed up the reading (but you will never reach the theoretical maximum).

I'm so sorry. The main point of my comment was that I have to send the power value (W) every 0.1 seconds, and the nocktime was too long.

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