Sleep power consumption and interrupt

I have a micro pro 3.3v, removed the power led and connected to a wind sensor (reed switch) through vcc and pin 2.

I use LowPower class to make it go to sleep for a 2 minutes

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

when sleeping the current is extremely low 0.18mA but I notice that it go up occasionally to 3mA (while still sleeping).

When I disconnect the pin 2 from the wind sensor it stays on 0.18mA.

which made me think that the pin 2 interrupt changes caused the current to go up.

Am I right? because in the code I do:
detachInterrupt(digitalPinToInterrupt(interruptPin));

before going to sleep.

any way to solve it?

thanks

const byte interruptPin = 2; //anemomter input to digital pin

void setup() {


  pinMode(interruptPin, INPUT_PULLUP); //set interrupt pin to input pullup
  attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING); //setup interrupt on anemometer input pin, interrupt will occur whenever falling edge is detected
    
  dataTimer = millis(); //reset loop timer




}

void loop() {

  unsigned long rTime = millis();
  if ((rTime - sTime) > 2500) pulseTime = 0; //if the wind speed has dropped below 1MPH than set it to zero

  if ((rTime - dataTimer) > MillisecondsBewtween) { //See if it is time to transmit

    detachInterrupt(digitalPinToInterrupt(interruptPin)); //shut off wind speed measurement interrupt until done communication
    float aWSpeed = getAvgWindSpeed(culPulseTime, avgWindCount) * 1.61; //calculate average wind speed

    culPulseTime = 0; //reset cumulative pulse counter
    avgWindCount = 0; //reset average wind count

    float aFreq = 0; //set to zero initially
    if (pulseTime > 0.0) aFreq = getAnemometerFreq(pulseTime); //calculate frequency in Hz of anemometer, only if pulsetime is non-zero
    float wSpeedMPH = getWindMPH(aFreq); //calculate wind speed in MPH, note that the 2.5 comes from anemometer data sheet
    //float wSpeedKPH = getWindKPH(wSpeedMPH); //calculate wind speed in MPH, note that the 2.5 comes from anemometer data sheet



      for (int i = 0; i < SleepAfter8s; i++) {
        LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);    // 8s is max for low.power lib, but with a 65 loops = 10mins
      }
       


    LastMSpeed = aWSpeed;


    Mcount = Mcount + 1;
    start = true; //reset start variable in case we missed wind data while communicating current data out
    attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING); //turn interrupt back on
    dataTimer = millis(); //reset loop timer
  }



}

On a related topic, millis (and micros) stops while in sleep / power down.

connected to a wind sensor (reed switch) through vcc and pin 2.

Since you have declared pin 2 to be INPUT_PULLUP, this should not work at all. The sensible approach would be to ground pin 2 through the reed switch, with interrupt triggered on FALLING.

detachInterrupt(digitalPinToInterrupt(interruptPin));

before going to sleep.

That should not work to wake the processor. There is rarely, if ever, a need to use detachInterrupt().

Since you have declared pin 2 to be INPUT_PULLUP, this should not work at all

What do you mean? it is working! it is taken from here:

That should not work to wake the processor. There is rarely, if ever, a need to use detachInterrupt().

I am not waking the process with detachInterrupt, it is waking after x seconds.

INPUT_PULLUP makes the pin HIGH.

Connecting the pin to Vcc through a switch makes the pin HIGH.

Please explain why one would ever expect the pin to be LOW, or to see a transition from LOW to HIGH.

Thanks for your help but I think I was wrong.

PIN 2 is grounded throw the wind sensor (black cable) as you said.
and when I disconnect the black cable that's when the power stays steady on sleep.

So if I get you right you are saying I need to change:

 pinMode(interruptPin, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING);

to:

 pinMode(interruptPin, INPUT_PULLUP); 
  attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, FALING);

?????

You should post the whole code. For example, it is not clear how SleepAfter8s is set, what is in anemometerISR etc.

FALLING is the correct parameter name. However, if it works as it is, then it does look like the pin is grounded by the reed switch. You will lose some energy through the pullup resistor (but nothing like 3mA) even when the mini is in sleep mode because presumably the reed switch will still be operating. You can disable the pullup before entering sleep mode and re-enable it on wake by manipulating pinMode() or the DDR register directly.

Edit:
It has occurred to me that you may not know when it sleep mode. You could switch a led (temporarily) say on in active mode and off in sleep mode, so you know what state it is in.

I've just looked at the circuit diagram in the video at 2.13 in ForceTronics: Measuring Wind Speed with an Anemometer and Arduino. Your 3mA comes from the 1K pull down resistor if the switch is closed. That debouncing is poorly executed. Better is to simply ignore pulses which come within X mS of the last valid pulse.

The anomolous power consumption is probably because you've left many pins to float.

Floating pins can consume power at random, should their voltage fall to somewhere midway between Vcc and ground.

What you can do is add this to the start of the setup() function:

void setup()
{
  for (byte i = 2 ; i <= 19 ; i++)
    pinMode (i, INPUT_PULLUP);

This prevents any pins floating.

According to this page by the venerable Mr Gammon

Testing in SLEEP_MODE_PWR_DOWN:

All pins as outputs, and LOW: 0.35 µA (same as before).

All pins as outputs, and HIGH: 1.86 µA.

All pins as inputs, and LOW (in other words, internal pull-ups disabled): 0.35 µA (same as before).

All pins as inputs, and HIGH (in other words, internal pull-ups enabled): 1.25 µA.

Note: This was tested with nothing connected to the pins. Obviously if you have an LED or something like that on an output pin, you will draw more current.

No, this is not my experience (Gammon was lucky with his tests?).

I've seen an ATmega pull ~2mA from floating inputs. As I said the voltages have to end up
mid-rail (or be coupled to some ac interference that sweeps them across mid-rail). This is luck
not judgement unless you use internal pullups.

In my case I was using a low speed clock (rather than sleeping), and powering the whole chip at 0.4mA
or so from a supply limited to 1mA, so those 2mA were a show-stopper.

Basically in any CMOS chip if an input is floating and held at mid-rail, you get shoot-through currents in
the first inverter driven by the pin. Typically these inverters use VLSI FETs with a channel resistance of
10k or so, leading to a few 100µA per pin of shoot-through current between the supply rails.

6v6gt:
I've just looked at the circuit diagram in the video at 2.13 in ForceTronics: Measuring Wind Speed with an Anemometer and Arduino. Your 3mA comes from the 1K pull down resistor if the switch is closed. That debouncing is poorly executed. Better is to simply ignore pulses which come within X mS of the last valid pulse.

And not use interrupts.

And he has the reed supply connected to Vcc instead of ground. Bit of a cowboy project overall!

This part did surprise me

LOW (in other words, internal pull-ups disabled)... This was tested with nothing connected to the pins.

Surely Nick Gammon would know that the pins would not be LOW, they would be floating.

MarkT:
No, this is not my experience (Gammon was lucky with his tests?).

When in sleep where I/O clock is stopped the digital input buffers are disabled (unless given pin is used as an wake up interrupt source). There is no extra current consumption for floating pins in power down mode.
Maybe the 3mA current spike is due to the MCU waking up between the 8s sleep chunks? When clocked from a crystal it waits noticeable time until the crystal (and BOD) stabilizes before the CPU is released from sleep only to discover that it should sleep for additional 8s.

Paul__B:
And not use interrupts.

The approach I took was to poll the pin connected to the anemometer every 1ms, enabling the internal pull-up before reading, then disabling it again afterwards (anemometer connected between pin and ground). I did not see any problems with bouncing, perhaps because 1ms is enough to avoid that with a reed switch (it would not be enough with a pushbutton). This was on a tiny85 @ 1MHz and using SLEEP_MODE_IDLE. I got it down to 0.5mA. When I get around to redesigning this sensor, I will use atmega328 and try the various sleep modes again.

Smajdalf:
Maybe the 3mA current spike is due to the MCU waking up between the 8s sleep chunks?

We suspect (the OP has not confirmed this) that the 3mA is caused by an external debouncing circuit between the anemometer and the Arduino, which includes a 1K pull-down, and the anemometer connected between 3.3V and the debounce circuit. This would flow for half the time when the wind blows (the reed switch probably opens & closes twice per revolution, if it's like mine). Or all the time or none of the time, if the air is still, of course!

PaulRB:
This part did surprise me

LOW (in other words, internal pull-ups disabled)... This was tested with nothing connected to the pins.

Surely Nick Gammon would know that the pins would not be LOW, they would be floating.

Look how old that is. It is probably old enough that INPUT_PULLUP did not exist and you had to use digitalWrite() to enable pullups. He is writing LOW to the inputs, not reading it.

The beauty of INPUT_PULLUP is that you can turn it off until you need to read the input.

Not for wake-up of course, but the OP does not want to use it for that as far as I can suss it out.

@Bamanio: Please clarify exactly how you wired the reed switch.

Is it connected between the pin and ground, or did you use the resistor/capacitor network shown in the video?

Wow!

I was not ready for all that information :slight_smile:

first, it's clear that you guys think that the debouncing is poorly executed

Your 3mA comes from the 1K pull down resistor if the switch is closed. That debouncing is poorly executed. Better is to simply ignore pulses which come within X mS of the last valid pulse.

And not use interrupts.

And he has the reed supply connected to Vcc instead of ground. Bit of a cowboy project overall!

but it's hard for me to understand how to implement it fully, does anybody have a link/sample/code for that? (I thought my solution is working well other than the 3 extra mA)

@Paul__B you suggested this:

The beauty of INPUT_PULLUP is that you can turn it off until you need to read the input.

Not for wake-up of course, but the OP does not want to use it for that as far as I can suss it out.

I did try setting PIN 2 as OUTPUT with LOW/HIGH and INPUT with LOW/HIGH before going to sleep (after the detachInterrupt) but all of the options were equal or worse than now.
Did I do it right?

@jremington I have the same as the video.
ground/pin2 throw debouncing with 2 resistors/capacitor/diod and throw black wind sensor wire.
The red wire from the wind sensor directly to 3.3V pin
its Inspeed Vortex like in the video.

thanks for all of your efforts.

(I thought my solution is working well other than the 3 extra mA)

As mentioned earlier, the extra ~3 mA comes from the 1K resistor to ground, when the reed switch is closed.

Use of INPUT_PULLUP should not matter.

I agree with the earlier suggestion to dispense with the switch bounce network. Connect the pin to the reed switch, which is grounded, and use INPUT_PULLUP to keep it HIGH when the switch is open.

Input polling would be better than using interrupts, with a simple debounce delay.