Basic firmware help required... help me understand clock speed.

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

 

Forgive me, I have very little experience on the firmware side of things.

 

I'm working from a simple WDT based LED blink example I found for the device I'm using (ATTINY10).  I'll include that below.  Eventually, my goal is to have the device "sleep" for a long period of time, wake up and turn on the light.  I wish for that "long time" to be configurable in minutes, hours, or even days, as I see fit.  But I'm not there yet.  This code is supposed to have the device go to sleep for 8 seconds and then wake and turn the LED on for 1 second, then repeat.

 

It more or less does that, but instead of 8 seconds it is 9 seconds. (to be clear, that extra second isn't due to the LED on time.  I mean it takes 9 seconds from LED off until LED on)

 

Question 1:  I gather that is because of the inherent inaccuracies of the internal oscillator.  Correct?  Or does it really take 1 second "wake up" or whatever?

 

For now, I simply thought it a good idea to lower the clock speed to increase battery life.

 

Question 2:  Is that correct?  Or I should just leave it in default?

 

The device has an internal 8MHz which is used by default, but it also has an internal 128kHz oscillator.

 

Scanning the datasheet, I thought all I had to do was set CLKMSR to 1 to turn on that oscilllator, but that didn't work.  I think I understand that's because it is a protected register (right?) so I have to send CCP = 0xD8; first.  That seemed to work.

 

I was a little surprised to see, however, that the delay didn't change at all.  It still took 9 seconds between blinks.

 

Question 3:  Is that because the WDT operates at that lower frequency anyway?  Or did I not do what I thought I did?

 

The time the LED stays on has been greatly reduced.  I would have though it would be the same (because I've defined F_CPU to match oscillator) or more (because every cycle takes longer), but not less.

 

Question 4:  Can you explain why the LED remains on for less time when the clock speed is lower?

 

 

Here is the code.  My modification to it being the first three lines

 

// CCP register must first be written with the correct signature - 0xD8
int CCP = 0xD8;
int CLKMSR = 1;
// define CPU speed - actual speed is set using CLKPSR in main()
#define F_CPU 128000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <util/atomic.h>
#include <avr/wdt.h>

// Wake up by WDT interrupt.
// Don't need to do anything here but (auto-) clearing the interrupt flag.
EMPTY_INTERRUPT(WDT_vect)

/*
  Delay in powerdown mode. Wake up by watchdog interrupt.
 */
void delay_power_down_wdt(uint8_t wdto)
{
    wdt_reset();
    wdt_enable(wdto);
    WDTCSR |= (1<<WDIE);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    // Make sure interrups are enabled and the I flag is restored
    NONATOMIC_BLOCK(NONATOMIC_RESTORESTATE)
    {
	sleep_cpu();
	wdt_disable();
    }
    sleep_disable();
}

int main(void)
{
    DDRB = 1<<2;

    sei();

    while(1)
    {
	// Short flash
	PORTB |= 1<<2;
	_delay_ms(1000);
	PORTB &= ~(1<<2);

	delay_power_down_wdt(WDTO_8S);
    }
}
Last Edited: Fri. Apr 7, 2017 - 05:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The WatchDog  oscillator is the LEAST accurate of all the possible oscillators in an MCU. Because of its primary function (to try to prevent "runaway" code), there is no particular effort toward precision.

 

Contrary to popular opinion, slowing the clock rate does not really reduce power consumption. You gain much more by having it run fast, then sleep long. That is because battery life is really a measure of stored energy and an MCU TENDS to use a specific quantity of energy for each instruction executed. Thus, to perform a given task, it generally takes the same ENERGY whether clocked fast or slow. You tend to benefit by executing fast and sleeping longer (because sleep uses less energy per unit time than slow execution does).

 

If you have defined F_CPU properly so that it reflects the actual clock speed, delays will turn out the same interval, no matter what the clock rate is.

 

Not sure about your last question.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Fri. Apr 7, 2017 - 05:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, thanks.  Can I at least depend on consistently inaccurate operation?  Ie.  if "8 seconds" actually take 9 seconds, will it always take 9 seconds? Or is it going to vary from time to time?  By how much?

 

For my current purpose, accuracy is not important... although I need SOME kind of predictable behavior.  Can I at least depend on +/- 30% do you think?

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

s_mack wrote:
Ie. if "8 seconds" actually take 9 seconds, will it always take 9 seconds? Or is it going to vary from time to time? By how much?

What does thee datasheet say?

 

... and so on.

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

theusch wrote:

What does thee datasheet say?

 

A lot.  It is quite overwhelming and takes time to get as familiar as you are, I suppose.  Thanks for the tips.  It didn't occur to me to look at the graphs for this.  In retrospect, of course, that's perfectly reasonable.

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

s_mack wrote:
// CCP register must first be written with the correct signature - 0xD8

int CCP = 0xD8;

int CLKMSR = 1;

If these are indeed the first three lines of your program, they are not doing what you think (unless your tools are much different than mine).

These (probably) need to be moved to inside the main() routine to actually be executed.

int main(void)
{
    CCP = 0xD8;     // Load Configuration Change Parameter
    CLKMSR = 0x00;  // Change Clock Settings Register (0x00=Internal 8MHz oscillator, 0x01=Internal 128KHz oscillator)
  ...  

 

David

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

Ahhh... OK, thanks frog.  I guess the note in the code:

actual speed is set using CLKPSR in main()

 

could have been my clue   lol