Hi
I have made a simple code utilizing ATTiny85 Micro controller and Push Button to toggle the led . Now i want to reduce the power consumption of ATTiny85 by adding watch dog timer in this code .Seeking assistance from members to add the watch dog timer.
If there is no input from the button for a 2 second , ATTiny85 will go into sleep mode and turned off LED (if its in ON).
The led turns on as soon as the ATTiny85 receives input from the button.
Actually i want to use this sleep mode in NRF24L01 + ATtiny85 used single button remote control . After ATtiny hook up with nrf24l01 there is only a pin remains.
I'm working on something similar at this very moment with the exception that I am using a PIR detector (array) instead of a push button. The code is below and may help you.
With an ATtiny85 you have to use pin change interrupts to wake a device from sleep mode. An external edge triggered interrupt will not work on this device (it would, however, on an ATmega328P as found on say the Uno).
/*
* PIR / ATtiny85
*
* See https://www.gammon.com.au/forum/?id=11497
*
* Notes:
* compiler options: (ATTinyCore): 1MHz clock, B.O.D. 1.8volts
*
Author: 6v6gt
*/
#include <avr/sleep.h>
const uint8_t inPin1 = 3 ; // PB3 (D3) LOW => detect (inverted with NPN)
const uint8_t ledPin = 0 ; // PB0 (D0) power leds
const uint8_t ldrPowerPin = 1 ; // PB1 (D1) top end of LDR
const uint8_t ldrAr = A2 ; // PB4 (A2) LDR ambient light
const uint8_t indLed = 2 ; // indicator (debug)
// bool inWake = true ;
uint32_t inWakeAtMs = millis() ;
uint32_t inStateAtMs = 0 ;
enum State { AWOKEN, CHECK_WAKE_SOURCE, MAIN_LED, CLOSE_DOWN, SLEEP } ;
State state ;
ISR (PCINT0_vect) // Interrupt service routine
{
// all handled in loop() at wake point.
}
void setup() {
pinMode( inPin1, INPUT_PULLUP ) ;
pinMode( ledPin, OUTPUT ) ;
pinMode( indLed, OUTPUT ) ;
pinMode( ldrPowerPin, OUTPUT ) ;
Serial.begin( 115200 ) ;
// pin change Interrupts
GIMSK = bit (PCIE);
PCMSK = bit (PCINT3); // PB3
}
void loop() {
switch ( state ) {
case State::CHECK_WAKE_SOURCE : {
// check we have woken from PIR (not a timer interrupt etc.)
if ( ! digitalRead( inPin1 ) ) { // LOW = triggered
//
state = State::AWOKEN ;
}
else {
// back to sleep
state = State::SLEEP ;
}
break ;
}
case State::AWOKEN : {
// terminate pin change interrupts
// GIMSK = 0 ; V0.06
// switch on ADC
ADCSRA |= bit(ADEN) ; // adc on
delay(10) ;
digitalWrite( ldrPowerPin, HIGH ) ;
// stabilise and test light level
delay( 10 ) ; // stabilise before checking LDR
if ( analogRead( ldrAr ) < 200 ) {
// digitalWrite( ledPin, HIGH ) ;
analogWrite( ledPin, 127 ) ; // was 63 Max 255 TD01
digitalWrite( indLed, HIGH ) ;
inWakeAtMs = millis();
state = State::MAIN_LED ;
}
else {
inStateAtMs = millis() ;
state = State::CLOSE_DOWN ;
// seems to have cleared TD01 issue.
analogWrite( ledPin, 0 ) ; // TD01
digitalWrite( ledPin, LOW ) ; // TD01
}
digitalWrite( ldrPowerPin, LOW ) ;
break ;
}
case State::MAIN_LED : {
if ( ! digitalRead( inPin1 ) ) {
inWakeAtMs = millis(); // reset timer
}
else if ( millis() - inWakeAtMs > 4000UL ) {
analogWrite( ledPin, 0 ) ; // TD01
digitalWrite( ledPin, LOW ) ;
inStateAtMs = millis() ;
state = State::CLOSE_DOWN ;
}
break;
}
case State::CLOSE_DOWN : {
if ( millis() - inStateAtMs > 500UL ) {
noInterrupts() ; // suspend interrupts until start of sleep V0.06
// unset any pending interrupts
GIFR = bit( PCIF ) ;
digitalWrite( indLed, LOW ) ;
// switch off ADC
ADCSRA &= ~bit(ADEN) ;
// reattach interrupts
// GIMSK = bit(PCIE);
state = State::SLEEP ;
}
break ;
}
case State::SLEEP : {
set_sleep_mode( SLEEP_MODE_PWR_DOWN ) ;
sleep_enable() ;
// Do not interrupt before we go to sleep, or the
// ISR will detach interrupts and we won't wake.
noInterrupts ();
// turn off brown-out enable in software
// BODS must be set to one and BODSE must be set to zero within four clock cycles
// original ATMEGA328P only ?? MCUCR contains attiny ISC00 and ISC01
// TD01
MCUCR |= ( bit (BODS) | bit (BODSE) );
// he BODS bit is automatically cleared after three clock cycles
MCUCR &= ~bit (BODSE);
// We are guaranteed that the sleep_cpu call will be done
// as the processor executes the next instruction after
// interrupts are turned on.
interrupts (); // one cycle
sleep_cpu() ;
// wake here ******************
sleep_disable() ;
state = State::CHECK_WAKE_SOURCE ;
break ;
}
}
}
If you have a single button which is to switch on an NRF24L01 for a few seconds then the whole thing powers down, another option is to use a latch circuit What is correct way to make latch power ciruit for arduino? - #9 by ShermanP. The button switches the latch on and everything powers up and the transmitter sends its payload. After a predefined time, the program breaks the latch and it all powers down. I'll still be curious to see how far you get using the watch dog timer in this role, however.
Using NRF24L01 and an ATtiny85, I created one remote control. This remote control just has one button and is powered by a 3.2 volt coin battery.When press the power button ATTiny TX circuit will send the signal to Arduino Uno RX module.If there is no input for 2 second the ATTiny TX module will goes to sleep mode till further input.
I want to reduce the power consumption when remote not in use.
It sounds like a garage door opener type application. At the expense of a few extra components, the latch will give zero power consumption during shutdown phase. Before going too far, though, check the coin cell can even power the NRF24L01. You may need to use a lithium cell and/or a big capacitor across it. Depending on the NRF24L01 clone, you may discover anyway that you have to disconnect the power to it to minimise standby current consumption.
Here's another version of the latching circuit which only uses one pin. The GPIO pin is configured as INPUT_PULLUP, which turns on the lower mosfet. But pushing the button will bring it low. That turns off the lower mosfet, but the button itself is now grounding the gate of the main mosfet, keepoing it turned on. So the single pin acts as both output and input.