"ATtiny85 Low-Power Timer" code. I have a few questions about this code.

So I’m working on a project using the ATtiny85. I’ve done a few builds with this little guy some I’m trying to dive deeper into what it can do.

For the first version, I’m trying to make a timer that vibrates a motor every 5 min. I’m trying to get it to run from a coin cell battery and if I could get it to last for at least a week wearing it roughly 8 hours a day that would be amazing!

From what I understand I can get this thing to go to sleep, in between the vibrations, and it will draw next to nothing. I have to get it into SLEEP_MODE_PWR_DOWN.

I’ve found this example and while I understand for the most part most things do, there is one part that is quite confusing. Here is the example code I’ve found.

/* ATtiny85 Low-Power Timer */
//from http://www.technoblogy.com/show?KX0


#include <avr/sleep.h>

// Utility macros
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)
#define adc_enable()  (ADCSRA |=  (1<<ADEN)) // re-enable ADC

// constants 
const int Speaker = 1;              // speaker pin
const int Lamp = 0;
const unsigned long Alarm = 900000; // alarm time - 15 minutes
unsigned long StartTime = 0;        // start time

void setup()
{
  pinMode(Lamp, OUTPUT);
  pinMode(Speaker, OUTPUT);
  adc_disable(); // ADC uses ~320uA
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}

void enterSleep(void)
{
  sleep_enable();
  sleep_cpu();
}

void playBeep(void)
{
    for (int i=0; i < 500; i++)
    {
      digitalWrite(Speaker, HIGH);
      delay(1);
      digitalWrite(Speaker, LOW);
      delay(1);
    }
}

void flashLed(int wait)
{
    digitalWrite(Lamp, HIGH);
    delay(wait);
    digitalWrite(Lamp, LOW);
}

// Main loop ----------------------------------------------

void loop()
{
  // Long flash
  flashLed(125);
  delay(125);
  flashLed(125);
  do
  {
    // Flash light
    flashLed(1);
    delay(2000);
  } while (millis() - StartTime < Alarm);
  // Alarm
  playBeep();
  enterSleep();
  // Continue after reset
}

Here here is my question.

void enterSleep(void) Could this also be written as void enterSleep() or should I be declaring that it takes no parameters? I thought that the void keyword pretty much says it returns no information. Is this some sort of good practice thing I should be doing?

void enterSleep() is the more common way to declare that.

I couldn't say why the code you found does it that way - I have seen that before, but very rarely. It's not necessary, and I don't think there's any best-practice reason to do it.

I couldn't say why the code you found does it that way - I have seen that before, but very rarely. It's not necessary, and I don't think there's any best-practice reason to do it.

That's a relict of back when Kernighan/Ritchie C was the way to program. Nowadays C and especially C++ don't need to declare that there are no parameters by using the keyword "void".

If you're able to program your Attiny85 using Atmel Studio, then you can drop the clock speed down to 128kHz by running off the WDT. This will result in a current consumption of only ~400 uA while awake (even lower while sleeping)! They're normal consumption at more typical clock-speeds of 8 MHz is closer to 5 mA.

Also, if you're powering from a coincell, I've found the Attiny85-10x versions to perform far better. They have a lower operating voltage over the Attiny85-20x versions, which is important because coincells frankly suck and experience significant voltage droop as they discharge, which will cause the Attiny85-20x to brown-out or behave erratically.

But I'm skeptical you'll get very good results with a coincell driving a vibrating motor, even given how tiny they are. Without seeing your specific motor, I can say most of the vibrating motors I've seen still pull at least 30-40 mA while running, and that's at barely-higher-than-stall running levels. A coincell will have a very difficult time keeping up with that, even if you use a large one like a 2032.

A CR2032 has a typical capacity of ~230 mAh, but they're designed for a very low discharge rate, on the order just a couple mA. I think the 2025 and 2032 may have a max safe discharge rating from the manufacturers of ~5-8 mA, but at that high rate of discharge you won't see anything near 230 mAh out of it, more like half-that. And when your motor kicks on, you'll likely see a rapid voltage drop from the cell that slowly recovers after the motor shuts off.

Go ahead and try it, though, I'll be interested to see what you run into.

Taking a look at your code, its very blocking and results in the attiny being awake for "long" periods to run through the code. Instead you could think about using a couple different sleep modes with the WDT. PWR_DOWN for the in-between periods for max energy saving, then you could use SLEEP_MODE_IDLE for executing your sequence since that allows for PWM to keep going while the chip is asleep. Then you could use the number of wakeups sort of in-place of millis() as a timer to set event flags that tell your peripherals what to do. This will go a long way toward reducing your total current consumption.

Here's a thread from back when I was sorting through a lot of this that may be helpful.