What is the real frequency of an ATMega328?

I want to build a very low power temperature/humidity sensor. I was inspired by Nick Gammons forum (thanks so much Nick for the enormous help you provide there!) and built a standalone atmega328, added a lillypad bootloader and started experimenting. I did several sketches I found at Nick’s forum and my results pretty well apporached his. One of the things I could not figure out was how to measure processor frequencies. I found in “Arduino Internals” from Dale Wheat a way to lower the processor frequency in software, like:

   const uint8_t prescale_factor = 2; // Lilllypad has an internal clock of 8Mhz
   const uint8_t prescale_multiplier = (1 << prescale_factor);
   noInterrupts ();
   CLKPR = (1 << CLKPCE);
   CLKPR = prescale_factor; // set it back a factor 4: 2 Mhz
   interrupts ();

It seems to work, as delays last longer (so I divide the delay time by the prescale_multiplier) and I have to divide the baud rate in the serial monitor by the prescale_multiplier as well. I have several issues with this approach:

  • How do I know what the “real” frequency is of the CPU? Using F_CPU does not help as it only returns the value in boards.txt.
  • When I set a baud rate of 9600, my serial monitor should be set to 2400 (in the example above). I thought to be clever and to multiply the baud rate by the prescale_multiplier, yielding 38400 but that results in gibberish. Highger baud rates seem hardly possible when changing the processor frequency
  • I also read that lower batter voltages yield lower frequencies. Does this mean that I should deduce the current prescale_factor and _multiplier and adjust all my timing settings or is this handled automatically at startup?

Thanks in advance for any answer!

I suspect you are over-thinking the problem.

I want to build a very low power temperature/humidity sensor.

Using the Internal Calibrated RC Oscillator?

A temp/humidity sensor will most probably not take readings continuously, but only in certain intervals. So your sketch should put the processor to sleep most of the time. Then the clock is stopped anyway. When awake, a faster clock will make everything faster, so you can go to sleep sooner, so slowing down the processor will not achieve a savings in energy. Read Nick's article(s) a few more times, I did so :-) It may be best to stick with the internal 8 MHz clock and the Lilypad bootloader to save you the hassle of recalculating all of you timings and baud rates. BTW lower voltages do not lead to lower frequencies, it is the other way around: with a lower clock frequency you can operate at lower voltages.

If you use an external crystal or resonator, the device determines the frequency.

If you use the AVR's internal 8 mhz reference, it will not be exactly 8 mhz but something close. While this is very easy to do and requires no external components, the system cost is that you get a clock that will change with temperature. This drift may be beyond what the other devices in the system can tolerate.

You can measure the clock frequency by writing a very small program in assembly to toggle a port pin. You then add up the total clocks required to execute the code and measure the time between pulses with an oscilloscope. Then the clock rate is the observed time divided by the clocks required by the code. You could also use a frequency counter to get the same information provided by scope with perhaps more precision.

Or set the fuse that outputs the system clock on one of the pins and measure it directly.

I agree with the above comments. You can tweak the internal RC frequency by changing the clock byte (OSCCAL) but there really isn't much point. You can also divide the clock by 8 to go from 8 MHz to 1 MHz (that's a fuse setting).

Really, though, stick to 8 MHz. My Temperature and humidity sensor - battery powered has been sitting here in this room for quite a while now, having done 38624 writes to the SD card, on the same set of 3 x AA batteries as when I started the project over a year ago.

So that's running the processor, taking measurements, writing to the SD card, and sleeping, without needing new batteries. I just measured the battery pack output as 4V, so that is 1.33V each. Judging by what I could find out about those batteries, there is still quite a bit of life left in them.

As the others said, dropping the voltage to the chip doesn't affect the frequency, until you hit the point at which it won't operate. A table of those voltages is on my page http://gammon.com.au/power.