ATtiny85 WDT and sleep modes.

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using the ATtiny85, ICCAVR(version 7.22C) and AS4.18

The main loop is only to generate a series of pulses until time to stop and delay for about 2 seconds
then resume with the Timer0 interrupt pulse outputs. This is a battery operated application,
so I thought using the 'do nothing' 2 second period , it would be better to use the sleep mode
if possible.

The existing code works exactly as I need, but would like to explore the sleep mode.

I would like to:

Quote:
Stop timer0 interrupts
Setup WDT interrupt mode for 2 seconds.
Execute sleep instruction, power down mode.

When WDT interrupt routine executes , re-enable Timer0 interrupts,
continue execution as before, the pulses for a while, then the 2 second delay, which could
include the sleep mode during the 2 second period and this would be the endless loop.

QUESTIONS:

Is this a good way to accomplish this?

ICCAVR: is there any function/library to execute the sleep instruction, or is
inline assembly the way or only way to go?

The tiny85 manual indicates :

Quote:
"If an enabled interrupt occurs while the MCU is in a sleep mode, the MCU wakes up. The MCU
is then halted for four cycles in addition to the start-up time, executes the interrupt routine, and
resumes execution from the instruction following SLEEP. "
I interpret that to mean that the WDT interrupt can re-enable the Timer0 interrupts
but that the RETI will execute the instruction following the sleep instruction.
I am not clear on what should follow the sleep instruction.
Any clarification or suggestions on implemented this approach?

I did use the sleep mode years ago with a ATtiny 12, but that project and code has long since
disappeared.

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the way to do it is rig up the longest 16bit overflow timer interrupt, and just asm("sleep") in the main loop, and the avr should wake up on the timer interrupt and start executing at the instruction after the sleep. The instructions before the sleep can do other power saving stuff like turn off the a/d, the pullups, etc. Then the instructions after the sleep should turn em all on again. I think.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So from your response, ICCAVR does not have
a particular function for SLEEP or WDT.
Using assembly is not an issue, I just thought might be one but did not find.

Any interrupt in the Tiny will wake the device. That is why I thought of using the WDT interrupt, it runs on a different clock that is not stopped by the sleep mode. That way I can set the sleep mode as Power-Down mode. This will not allow internal interrupts to wakeup the device. But, the WDT will wake up the chip and the WDT can generate an interrupt in lieu of a restart.
Also, the power-down mode has additional power saving modes.

I will keep plugging at it. I will look at your suggestion as well, thanks.

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After searching the Internet I see I may
be having a timing problem with the timing
constraints on changing the WDTCR to turn off the WDT. The Atmel Tiny85 manual doesn't give a lot of information in setting up the WDTCR to get things rolling.
It gives an example turn disable turn/off the WDT using 'C'. But one freaks post indicated that it may be required to write some of that code in assembly. I will check what the ICCAVR compiler produces.....

I will look at it again later, for now I will just drop it.

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I have everything working now almost
exactly as I want. The only issue now is the sleep mode current usage.
I have attached a PNG file that I hope clarifies what I am doing.
Also inserted the code. (ICCAVR version 7).

The current hardware is using a ULN2003 to drive the LED module. When I have completed the prototype I will built a separate board and use an N channel to interface the LED module to the 12 VDC battery.

QUESTION: Does anyone have experience in using the Tiny85, sleep mode and using the WDT (interrupt mode) ?

Also, I did not see any information in Atmel doc's that specify what the WDT current usage is.

I am thinking that I don't have everything setup to reduce current in the sleep mode.

Thanks in advance for all of the suggestions so far.

///////////////////////////////////////////////////////////////////////////////
// 06/23,2012  Experimenting with T85 and Timer1 interrupts
// 
///////////////////////////////////////////////////////////////////////////////

//   includes
#include "_iotX5v.h"
#include 
#include 

//changed to match the Atmel documentation/register definition name(s)
#define DT1A   (*(volatile unsigned char *)0x45)
#define DT1B   (*(volatile unsigned char *)0x44)
#define BYTE unsigned char
// globals
volatile unsigned char foo = 2;
unsigned int cntr;
BYTE HeartBeatRate = 20;


void port_init(void)
{
 PORTB = 0x3e;//00;   
 DDRB  = 0B00010001;        //make PORTB.0 PORTB.1 outputs
}

//TIMER1 initialize - prescale:4
// desired value: 1mSec
// actual value:  1.000mSec (0.0%)
void timer1_init(void)
{
TCCR1 |= (1<< CTC1 | 1 << CS12); // ck/8

TCNT1=0x64;
OCR1A=0x9c;
OCR1B=0x7D;
OCR1C=0x7d;
TIMSK |= (1<< OCIE1A);
TIFR=0x00;
GTCCR=0x00;
DTPS=0x00;
DT1A=0x00;
DT1B=0x00;
}

// Timer1 vectors:
// 		    OVF =  5 add= 0x004
//		  COMPA =  4 add= 0x003   <==== use this one
//		  COMPB = 12 add= 0x000b
#pragma interrupt_handler Tim1_COMPA:4
void Tim1_COMPA(void)
{
 // SetBit(PORTB,4);   // HeartBeat LED off every 1 ms.
  if(foo > 0)
  foo --;
 if(foo == 0)
 {
  cntr++;
  ToggleBit(PORTB,0);
  foo = 49;
 }
}// end Timer1 interrupt

#pragma interrupt_handler WDT_int:13
///////////////////////////////////////////
// WDT_int() Watch Dog Interrupt function
///////////////////////////////////////////
void WDT_int(void)
{
 SEI();
}//end WDT_int()
///////////////////////////////////////////
//set_wdt()
//configure WDT ,use WD interrupt, 2 sec.
//time out. This will enable the WDT
//////////////////////////////////////////
void set_wdt(void)
{
 asm("wdr");
 WDTCR |= (1<< WDIE) |( 1<<WDE) | (1<<WDP2) | (1<< WDP1) |(1<< WDP0);
}//end set_wd()

/////////////////////////////////////////
// wdt_off()
//Disable Reset Mode for the WDT
/////////////////////////////////////////
void wdt_off(void)
{
 asm("wdr");
 CLI();
 //   Start WDT disable timing sequence
 MCUSR = 0x00;
 WDTCR |= (1<<WDCE) | (1<<WDE);
 WDTCR = 0x00;
 // end WDT disable timing sequence
 
 TCCR1 |= (1<< CTC1 | 1 << CS12);
 MCUCR |= (0<< PUD)| (1 << SE  | 1<< SM1);   //set sleep mode for Power-Down
 //cntr=0;
 SEI();
}// end wdt_off

//////////////////////////////////////////
// init devices
//////////////////////////////////////////
void init_devices(void)
{
 CLI(); 
 port_init();
 timer1_init();
 ACSR |= (1<< ACD);//disable
 ADCSRA |= (0<< ADEN);//disable
 DIDR0 |= (1<< AIN1D)|(1 << AIN0D);//disable
 //GIMSK  = 0x00;
 MCUCR |= (1 << SE )|( 1 << SM1);   //enable power-down sleep mode.
 PRR |= (1 << PRTIM0 | 1 << PRUSI | 1 << PRADC); 
 PLLCSR = 0x00;
 SEI(); 
}
////////////////////////////////////////////////
//  main()         
////////////////////////////////////////////////
void main(void)
{
 init_devices();
 while(1)
 {
  if(cntr==50)
  {
   cntr=0;
   set_wdt();
   asm("sleep");
   wdt_off();
  }
 }// end while()
}//end main()

Attachment(s): 

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) How are you measuring current consumption? the AVR itself, or the input to a regulator?

2) What do you have connected to your AVR? There was a ULN2003 mentioned earlier. Tip: When searching for uA, start with the bare AVR. Minimum external components. Test by staying awake some seconds after reset (to allow measurement of active current), then go into your deep sleep. At this stage I have a minimal program that never awakens--reset the AVR to retest.

Once you are satisfied, then add external components one by one, and software features one by one. Retest at each stage.

IME if you start with the full app, you end up pulling things one by one anyway to figure out where the sucker is.

Quote:

Also, I did not see any information in Atmel doc's that specify what the WDT current usage is.

Figure 22-12. Power-down Supply Current vs. VCC (Watchdog Timer Enabled)

Whether ~5uA is "significant" depends on your app.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agree, it sould be in the few uA range. I'd start by taking out the 2003...Then look at port pins, are pullups turned off just before sleep?
Do you REALLY need the 2003 ? perhaps you could post your circuit...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

chartman :

Quote:
Do you REALLY need the 2003 ?

In the previous post
I stated:

Quote:
I will built a separate board and use an N channel to interface the LED module to the 12 VDC battery

I tried the different things mentioned in the post by theusch . Thanks foe your suggestions. I will continue looking at it from that approach.

I think I will just place the chip by itself in a breadboard setup. I have an 'old' Heathkit DigiTrainer which has a small bread board area and also has a 12 VDC and 5 VDC PS.
I will post the results and continue to find the answer.

I am not sure about the Port pin PU setting. I was thinking I had that part correct in the code ? BTW, the unused pins are floating, so that may be a problem as well.

I do recall in a previous project using a Tiny12 chip and using sleep mode, the current was in the uA range. So it has got to be something I am not doing right. :oops:

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I reprogrammed the T85 and placed in a breadboard. There are no external parts connected except for an LED connected to PORTB,0. This LED has a buffer much like the LED's on the STK-500.

I commented out the function call

set_wdt()

This is the routine that enables and starts the WDT to run.

I added a

while(1);

loop following the sleep instruction. I don't think the while(1); is needed as long as the T85 is in the sleep mode.

I observed that the LED 'blinked' per the code and then stopped after the sleep instruction. The LED is turned off after entering sleep mode.

I measured current as:

Quote:
Run before sleep, 2.14 mA.
After sleep: 1.46 mA.

The prototype board I used in the originally test did have other components, Max232 chip, a crystal not connected.

Now, All of those have been eliminated.
It must be the way I have set up the port pins. In the code I believe that I have set everything not required to off or stopped.

So ,that is where I am at this point.
Perhaps there is something in the code that is not correct?

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any unused pins must be set to be output, pullups off.....

Quote:
This LED has a buffer much like the LED's on the STK-500

All you need to drive an LED ( unless you want a searchlight) is a series 1K resistor. By buffer, do you mean a chip ? That's going to draw current ....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

1) How are you measuring current consumption? the AVR itself, or the input to a regulator?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used exactly this same technique, same chip even, and achieve about 50uA sleep current with a single AA cell to 5V boost regulator. So it's really possible :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I changed the code to just set PORTB
no timer interrupts no additional code,
No WDT enabled/running.

///////////////////////////////////////////
// 06/27,2012  Experimenting with T85 sleep mode
///////////////////////////////////////////

//   includes
#include "_iotX5v.h"
#include 

void port_init(void)
{
 PORTB = 0x00;   
 DDRB  = 0x00;
}
//////////////////////////////////////////
// init devices
//////////////////////////////////////////
void init_devices(void)
{
 CLI(); 
 port_init();
 ACSR |= (1<< ACD);//disable
 ADCSRA |= (0<< ADEN);//disable
 DIDR0 |= (1<< AIN1D)|(1 << AIN0D);//disable
 MCUCR |= (1<<PUD)|(0 << SE )|( 0 << SM1);   //enable idle sleep mode.
                                             // No interrupts to wakeup. 
 PRR |= (1 << PRTIM0 | 1 << PRUSI | 1 << PRADC); 
 PLLCSR = 0x00;
 //SEI(); 
}
void main(void)
{
 init_devices();
  asm("sleep");   
  //everything should now be in the sleep mode.
  // No interrupts used to wakeup.
 }//end main()

The chip is in a bread board supplied by 5 VDC. Nothing else is wired, just Power and ground. Measuring current from +5 to pin 8
VCC pin. In other words the Meter is between the +5VDC and the VCC device pin.

I am measuring 3.7 mA after sleep mode which is almost as soon as the program executes. See included code.

I have no LED's or anything else connected.

Is there a setup mistake in the code to
realize minimum sleep current consumption?

I tried several configuration on PortB setup and enable/disabled PUD in the MCUCR
register.

I am thinking this must be the problem, the setup. :cry:

Quote:
1) How are you measuring current consumption? the AVR itself, or the input to a regulator?

I am using the 5 volt output of the breadboard PS, no regulator, it is already
a regulated source from the Heathkit DigiTrainer.

Quote:
All you need to drive an LED ( unless you want a searchlight) is a series 1K resistor. By buffer, do you mean a chip ? That's going to draw current ....

No LED in circuit now.

jayjay1974: How do you setup the PORTB and
are the pins tied to anything in your measurement?

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to enable the SE bit in MCUCR first to enable sleep modes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jayjay1974 :

MCUCR |= (1<<PUD)|(0 << SE )|( 0 << SM1);   //enable idle sleep mode.

This is the code listing, see previous post. I don't think I would be able to get to go to sleep in order to measure the sleep current.

The above line of code insures that the idle mode of sleep is selected. Perhaps I should have selected the power down mode
instead.

In the previous code post(the most recent) I stripped out all of the code not needed to test the sleep mode.

I did not have any of the PORTB pins tied to anything, no LED or anything in the breadboard test setup. I could never get close to uA I expected.Even using the idle mode of sleep I would think it should be in the uA range(?).

In your test, did you tie the pins Hi/Lo?

Thanks again for your replies and efforts.
I know there must be something I am doing incorrectly , but just can;t see it :evil:

Well, I am thinking now that I will just use it as is with the exception of using
a N channel MOSFET to drive the LED module.

Also, I won't need any of the other parts located on the prototype PCBA.

I am tempted to open the LED module and see if it has anything other than a resistor. I can see one resistor and a diode under the module lens, and I did measure the module current. It is about 35 mA which account for the majority of current used in the non-sleep mode.

The battery is a 12 Volt 1.4 AH battery and should last for a while. I will only be using it about 45 min. to one hour about four or five days a week.

But, the challenge is to fabricate it correctly and have the off/sleep time working in the uA range.

I will try one more time and change the test program as in the previous/recent post
and set the mode to power down, but does leave the WDT running.

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But (0<<SE) is not setting the SE bit to one. Shifting zero any number of places still results in zero ;)

To get minimum power consumption in my project I disabled all peripherals with the PPR register, and it only wakes up by a pinchange interrupt; or a slowish WD interrupt in some other mode my device has.

I do not remember exactly what I did to the PORT pins; it powers a LCD module, so I guess it set it all to low output.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tubecut,

Perhaps you need a refresher course in

Bit Manipulation (AKA "Programming 101")

:)

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Perhaps you need a refresher course in

Bit Manipulation (AKA "Programming 101")

OK, so what part is incorrect?

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I see the bit assignment error. I must have changed it somewhere or else I don't see how I could execute Sleep mode.

BTW, after using the code and setting up
the chip, using a N channel MOSFET to drive
the LED module, and using the breadboard's
5 VDC and 12 VDC power supplies, I changed
the WDT to 8 seconds and then got to the
< 1.0 mA. My meter could not read any lower than that. :cry:

So, I will build up the board I am going to use and it should be fine.

I recharged the 12 volt battery and started
a test and measuring the voltage to get an idea of voltage loss over a period of time.
Previously it was dropping about 0.02 volts/hour. Even though I am still testing
with the same prototype board, I expect it to be lower.

Thanks to all for your individual input.

I'll believe corporations
are people when Texas executes one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can put a 1K resistor in series with the 5V, you can measure the volt drop across the 1K and ohms law will give you the current.Your voltmeter will probably have a lower volts scale than current ( perhaps 200mV)