Anti-consumption system in Arduino

to do: simulate the chandelier of a room with a led → if I turn on the led for 10sec I calculate the time it is on and calculate the consumption, then going to print the values on serial monitor, calculate average consumption, I have to use: interrupt → voltage surge → system goes into protection / light goes out I note it on EEPROM I put interrupt to restart everything (key that restarts my whole system)

for now I have done, but it doesn't work:

const int ledPin = 9;
const int buttonPin = 2;
unsigned long previousMillis = 0;
const long interval = 10000;
float energyConsumption = 0.0;
int numSamples = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();

  if (digitalRead(buttonPin) == LOW) {
    digitalWrite(ledPin, HIGH);
    previousMillis = currentMillis;
  }

  float onTimeSeconds = (currentMillis - previousMillis) / 1000.0;
  energyConsumption += onTimeSeconds * 0.01;
  previousMillis = currentMillis;
  numSamples++;

  if (currentMillis - previousMillis >= interval) {
    Serial.print("On-time: ");
    Serial.print(onTimeSeconds);
    Serial.print(" seconds | Energy consumption: ");
    Serial.print(energyConsumption, 2);
    Serial.println(" watt");

    float averageConsumption = energyConsumption / numSamples;
    Serial.print("Average consumption: ");
    Serial.print(averageConsumption, 2);
    Serial.println(" watt");

    digitalWrite(ledPin, LOW);
  }
}

could someone help me?

Welcome to the forum

You started a topic in the Uncategorised category of the forum

Your topic has been moved to a relevant category. Please be careful in future when deciding where to start new topics

Have a look at these three lines of your code:

previousMillis = currentMillis;
numSamples++;

  if (currentMillis - previousMillis >= interval) {

Can you see a problem there?

1 Like

I'm struggling with this collection of words. Could you please reformulate this passage so it's perhaps a little easier to understand for the rest of us?

several issues with the code

  • looks like the following intends to report values every 10 sec

but as already mentioned, because

occur just before it, the timer never expires. And if the above is commented out, the prints are repeated because previousMillis is never reset to currentMillis when the condition becomes true

don't understand the purpose of the button. why not generate a report every so many seconds

  • the following is invoked every iteration of loop (1000s time / sec)

so despite calculating onTimeSeconds, energyConsumption accumulates the value based on onTimeSeconds each iteration of loop instead of being based the value of onTimeSeconds

presumably the 0.01 is the consumption rate -- W/sec

  • if energyConsumption were strictly proportional to the time that the LED were on and it's value reported every 10 sec, that value would increment by 0.1 (10 * 0.01) each report

  • the average is based on numSamples, but it is incremented each iteration of loop and uncorrelated with and on period


guessing that the LED could be turned on and possibly off at random times, requiring monitoring it's on/off times. The accumulated time that it is on can be computed along with energy consumed. But reporting values should be period, using separate timestamps (not solely previousMillis)

consider the following approach for capturing the accumulated time that some input is active. presumably trivial to convert that time to Watts. Presumably average is that time divided by the total time (millis()).

const int PinLed = 9;
const int PinInp = 2;

byte inpState;

unsigned long Period    = 5000;
unsigned long msecLst;
unsigned long msecOff;
unsigned long msecOn;
unsigned long msecSum;

enum { InpOff, InpOn };

char s [90];

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();

    byte inp = digitalRead (PinInp) == LOW;
    if (inpState != inp) {
        inpState = inp;

        if (InpOn == inp)
            msecOn  = msec;
        else
            msecSum += msec - msecOn;

        delay (20);         // debounce mech sw used to test
    }

    if (msec - msecLst >= Period)  {
        msecLst = msec;

        if (InpOn == inp)  {
            msecSum += msec - msecOn;
            msecOn   = msec;
        }

        sprintf (s, " %6lu msec total", msecSum);
        Serial.println (s);
    }
}


// -----------------------------------------------------------------------------
void setup () {
    pinMode (PinLed, OUTPUT);
    pinMode (PinInp, INPUT_PULLUP);
    inpState = digitalRead (PinInp);
    Serial.begin (9600);
}

It should work (didn't test) but msecLst hasn't been explicitly initialized.

is strange except maybe for Yoda from Star Wars but
if (LOW == buttonState) {...} is valid as well...

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