3

Context

I am building a small battery powered counting device. As with many other projects like this, saving power is critical. I am therefore trying to utilise the sleep mode wherever possible. This is using a 328P as a standalone MCU running on the 1MHz internal clock

The Hall Effect sensor I am using outputs Vcc when nothing is detected, and Ground when something is detected. It therefore seems well suited to being used as a trigger for an interrupt to wake up the 328P from sleep (so that I don't even need to use a watchdog timer.)

Below is an excerpt from my code. This code does put the processor into sleep as desired. However, from testing I have discovered that the device will not sleep when the magnet is left near the sensor, as its output stays LOW. As I only want to detect pulses of a moving piece of metal, this is wasting power. I only want to wake up when it is initially detected on each cycle.

void sleepLoop()
{
  Serial.print("S");

  delay(5);   //scales to 40ms

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  noInterrupts();

  attachInterrupt(digitalPinToInterrupt(countInterruptPin), sleepInterrupt, LOW);

  interrupts();
  sleep_cpu();

  //The program will continue from here.

  //First thing to do is disable sleep.
  sleep_disable();
}

I therefore changed

attachInterrupt(digitalPinToInterrupt(countInterruptPin), sleepInterrupt, LOW);

to

attachInterrupt(digitalPinToInterrupt(countInterruptPin), sleepInterrupt, FALLING);

PROBLEM

Now my processor never goes to sleep. For debugging I have put in a serial print at the start of the loop so that I know it has entered this loop of code. Whether LOW or FALLING is used the 'S' is printed. I only know it is not sleeping because I am measuring the current flow.

I thought the sensor may be going LOW long enough to keep the device awake, but not long enough to register as a count (as I have a debounce in there) so I have checked the output from the sensor with an oscilloscope in case it was momentarily going LOW, but I couldn't see any sign of this.

The findings from the oscilloscope make me feel like there is something about the interrupt function that I am overlooking. Any help would be greatly appreciated!

  • Could not reproduce. Power usage goes down in both cases and with FALLING I only get a single S printed when signal is low (and sometimes when it goes back high). Are you sure your hall-effect sensor doesn't need a pull-up resistor? What kind of serial output do you get? What is the power-usage (normal, during sleep, during "apparently not sleep")? – Gerben Oct 22 '15 at 13:09
  • Thank you for looking at this :) For me it is very repeatable. Also, I only ever get a single S. It must receive an input before being able to print S again. Datasheet claims 'No External Pull up Resistor Required'. Power usage is ~0.6mA @ 3.6V when awake, and 0.02mA @3.6V when asleep. When in 'not-asleep' its ~0.6mA, hence I believe it is awake – Dan Evans Oct 22 '15 at 13:19
  • As you didn't have the same problems, I wonder if it is something else I have done.. My full code is here: github.com/danjuggles/Sleep-and-counter/blob/master/… – Dan Evans Oct 22 '15 at 15:10
  • Looking at the serial output, sleepLoop is never called. So all the code above has nothing to do with the problem. – Gerben Oct 22 '15 at 16:20
  • I just retested this code and I am getting the correct Serial output.. I am underclocking the processor so: Serial.begin(38400); //Use Baud rate at 4800 on PC (due to 1MHz clock speed) // (38400/8)=4800 – Dan Evans Oct 23 '15 at 7:17
2

Only low level detect is possible with external interrupt pins (INT0/D2 and INT1/D3) in power down sleep mode. The signal must be low for a number of clock cycles to be detected and the interrupt will detected while the signal is low (and the interrupt is enabled). It is not a transition.

A pin change interrupt could be used instead.

For more details please see chap. 9.5 Power-down Mode and chap. 12. External Interrupts.

Cheers!

0

There is a more radical alternative, that could yield even higher power savings: use the HAL sensor to trigger a monostable circuit that normally would keep the uC (and the clock source) powered off.

When it starts, get it to update the counter and time the monostable so that it shortly puts the rest of the system back to off.

You can use the eeprom for the counter.

For improved efficiency, get rid of the bootloader and start executing your application right away. If you program from the ISP interface, you do not need the bootloader.

  • Were filtering contact/range bounce not likely necessary the ATmega counter timer block could probably be configured to count without waking up the processor at all. But wakeup is not that expensive and has nothing to do with the bootloader as it does not mean the CPU reboots. – Chris Stratton Dec 3 '15 at 17:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.