ATTINY85 Timer Questions

Thread Starter

fredric58

Joined Nov 28, 2014
203
Hello, These questions are based on a project that originated and was constructed and credited to Mr. Nick Gammon. February 2014 entitled "ATtiny85 Torch Locator", Used in the event of a power outage to find a flashlight. "The device powers down for 2 seconds until woken up by the WDT. Then it does a ADC read (analog read) of the LDR (light dependent resistor) to see if it dark or not. If it is not dark it goes back to sleep."

This is great if being used in a power outage situation. If the desire is simply to determine whether it is day or night. QUESTION 1: Is it possible and would it conserve any power to have it do the analog read every 5 minutes or say every 15 minutes or even every half hour?

"If it is dark, then the code turns timer 0 back on (so that millis() will work) and then turns on the LED, waits 2 mS, and turns it off again. This brief flash is plenty to spot the LED in the dark."

QUESTION 2: Is it possible to turn the LED on for 15 - 30 seconds, wait 5 minutes, repeat, until Light?

I have just begun learning about Low Power, Timers and their limitations.

Thank you. I hope this is posted in the right place and format, and direct!



Code:
// ATtiny85 torch detector
// Author: Nick Gammon
// Date: 25 February 2015

// ATMEL ATTINY 25/45/85 / ARDUINO
// Pin 1 is /RESET
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

/*

  Pin 2 (PB3) <-- LDR (GL5539) --> Pin 7 (PB2) <----> 56 k <----> Gnd

  Pin 5 (PB0) <---- LED ---> 100 R <-----> Gnd
 
*/


#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management
#include <avr/wdt.h>      // Watchdog timer

const byte LED = 0;          // pin 5
const byte LDR_ENABLE = 3;   // pin 2
const byte LDR_READ = 1;     // Ain1 (PB2) pin 7
const int LIGHT_THRESHOLD = 200;  // Flash LED when darker than this

 // when ADC completed, take an interrupt
EMPTY_INTERRUPT (ADC_vect);
 
// Take an ADC reading in sleep mode (ADC)
float getReading (byte port)
  {
  power_adc_enable() ;
  ADCSRA = bit (ADEN) | bit (ADIF);  // enable ADC, turn off any pending interrupt
 
  // set a2d prescale factor to 128
  // 8 MHz / 128 = 62.5 KHz, inside the desired 50-200 KHz range.

  ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2);
 
  if (port >= A0)
    port -= A0;
    
#if defined(__AVR_ATtiny85__) 
  ADMUX = (port & 0x07);  // AVcc   
#else   
  ADMUX = bit (REFS0) | (port & 0x07);  // AVcc   
#endif

  noInterrupts ();
  set_sleep_mode (SLEEP_MODE_ADC);    // sleep during sample
  sleep_enable(); 
 
  // start the conversion
  ADCSRA |= bit (ADSC) | bit (ADIE);
  interrupts ();
  sleep_cpu ();     
  sleep_disable ();

  // reading should be done, but better make sure
  // maybe the timer interrupt fired

  // ADSC is cleared when the conversion finishes
  while (bit_is_set (ADCSRA, ADSC))
    { }

  byte low  = ADCL;
  byte high = ADCH;

  ADCSRA = 0;  // disable ADC
  power_adc_disable();
 
  return (high << 8) | low;
 
  }  // end of getReading
 
// watchdog interrupt
ISR (WDT_vect)
{
   wdt_disable();  // disable watchdog
}  // end of WDT_vect

#if defined(__AVR_ATtiny85__) 
  #define watchdogRegister WDTCR
#else
  #define watchdogRegister WDTCSR
#endif
 
void setup ()
  {
  wdt_reset(); 
  pinMode (LED, OUTPUT);
  pinMode (LDR_ENABLE, OUTPUT);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  }  // end of setup

void loop ()
  {
  // power up the LDR, take a reading
  digitalWrite (LDR_ENABLE, HIGH);
  int value = getReading (LDR_READ);
  // power off the LDR
  digitalWrite (LDR_ENABLE, LOW);
 
  // if it's dark, flash the LED for 2 mS
  if (value < LIGHT_THRESHOLD)
    {
    power_timer0_enable ();
    delay (1);  // let timer reach a known point
    digitalWrite (LED, HIGH);
    delay (2);
    digitalWrite (LED, LOW);
    power_timer0_disable ();
    }
 
  goToSleep ();
  }  // end of loop
 
void goToSleep ()
  {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts ();       // timed sequence coming up

  // pat the dog
  wdt_reset(); 
 
  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset, clear existing interrupt
  watchdogRegister = bit (WDCE) | bit (WDE) | bit (WDIF);
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  watchdogRegister = bit (WDIE) | bit (WDP2) | bit (WDP1) | bit (WDP0);    // set WDIE, and 2 seconds delay
 
  sleep_enable ();       // ready to sleep
  interrupts ();         // interrupts are required now
  sleep_cpu ();          // sleep               
  sleep_disable ();      // precaution
  }  // end of goToSleep
 

Thread Starter

fredric58

Joined Nov 28, 2014
203
Thank you, so on part 1. Ex: 10 minutes from the WDT ???

Code:
// sleep for a total of 600 seconds
  int i;
  for (i = 0; i <=75; i++)
  {
    myWatchdogEnable (0b100001);  // 8 seconds
 
Top