Libraries make invalid assumptions of CPU clock

The libraries seem to use a command line option for the CPU clock speed. This seems nonsensical. There is nothing that requires the CPU speed remain constant. I found that when I reduced the CPU clock speed to save power, everything stopped working correctly; for example, if I set the clock speed to 1MHz, millis() gives the wrong value (off by 16x).

There is no option I can find that lets me specify the clock speed. Furthermore, I would like a clock speed of 0hZ to be specifiable, which means that the library has to read the instantaneous clock speed from the control registers. This is because I really want to go below 1MHz, which is the limit for successfully writing the EEPROM. When I want to write to the EEPROM, I will set the clock speed to 8MHz or something else suitable and consistent with extreme battery power management. I want all the libraries that think they know about the clock speed to use 0 clock speed to force code to be generated to get the actual clock speed at runtime, whatever it might be at the current instant.

In many applications, you will actually get lower power consumption by using a higher clock speed, then putting the microcontroller to sleep whenever it isn't doing anything. The reason is that the higher clock speed allows it to get business done quickly and back to bed. But it depends on the requirements of the specific application. In some cases, it's necessary to stay awake even when the CPU isn't doing anything and in those cases the lower clock speed is helpful.

Depending on which microcontroller you are using, there are 3rd party boards platforms that add custom board options to allow the user to select the clock speed. For example:
https://github.com/MCUdude/MiniCore#supported-clock-frequencies

I'm not sure you will find many libraries that contain such code. You can add it if you prefer though. The menu I mention above is just setting the value of the F_CPU macro at compile time.

I guess that that is how it was designed. Don't forget that the complete Arduino environment was designed with beginners in mind; fiddling with registers is not something for them.

If you want to have an option for e.g. a 328P on 1 MHz, you can create an entry in boards.txt.

I don't understand; I've never had a problem writing to EEPROM at 16 MHz.

There are a lot of myths about what "beginners" need. It is particularly annoying when there is this condescending attitude that "beginners don't need to do that". They do. For example, beginners need to see the preprocessor output. They don't know it until they need to do it, and when they need to do it, they should be able to. Beginners don't need to define symbols on the command line, until they do, then they should be able to. Not permitting something because someone "knows" beginners "don't need that" doesn't understand "beginners" or "need".

The problem is that the clock is not compile-time-known. It is only known once the clock speed is set. Therefore, it is not a constant. It depends on the current clock speed, whatever that is. It is not fixed. I should have a setClockSpeed() call which makes everything that depends on the command line clock speed to be adjusted to work properly.

And no, you wouldn't have any problems writing EEPROM at 16MHz, it is specified down to 1MHz. But below 1MHz, which is where we want to spend most of our CPU clock time, it is not guaranteed to work. The problem is that there is no way to "graduate" to another environment. The libraries need to generalize. If I go to VS Code, the library source is still wrong for dynamic clock speed.

Why would anyone think that a "beginner" does not need to change clock speed? A system that is developed for someone with a week of experience and can't deal with someone with six months experience is not a very good design. A "beginner" who wants to do a project that runs on a small battery and doesn't need service for months is still a beginner.

Because they have experience in teaching beginners maybe? Something that you appear to lack.

F_CPU is just a convenient compile-time default. I need to change the clock at runtime. I have a spreadsheet that shows me the time spent at various clock speeds and works out the power consumption based on the extra time required, and it still shows me that a sub-megahertz clock uses less battery, even though it takes longer. The longer time doesn't cost as much as the faster clock.

Good for you.

Now if you are serious about low power consumption then use a processor that is designed for that, the normal Arduino processors are not.

Are you referring to AVR processors?

I believe that the Nano Every and Uno WiFi 2 (with their ATmega4809) have been modified to allow run-time changes in clock speed. At rather great cost to those functions that are cpu-speed dependent :frowning: (tick interrupt on Uno: 148 bytes. On Every: 200 bytes .)

The problem is that the clock is not compile-time-known. It is only known once the clock speed is set.

Not a problem. Within the Arduino environment, there IS not way to "set the clock speed" to a value other than that of the crystal.

Why would anyone think that a "beginner" does not need to change clock speed?

Well, in ~15 years of Arduino, it hasn't been requested very often. It's pretty uncommon in "experienced" circles, since as Pert says, practice has shown that it's not the best way to conserve power.

A "beginner" who wants to do a project that runs on a small battery and doesn't need service for months is still a beginner.

Maybe the "beginner" should learn:

  1. There aren't really any official Arduino devices designed for minimal power use. Even at 16MHz, the "extra stuff" on a Uno probably consumes more power than the AVR itself.
  2. Changing the clock speed "dynamically" has far-reaching implications (did you want the UARTs to automatically restart with a new BRG value? What about the PWMs? What if the new clocks make those have impossible values for the libraries that are in use?)
  3. The best way of reducing overall power consumption does not involve changing the clock frequency.

Utra-low power consumption really isn't a "beginner" topic. It's complicated.

52 bytes to get the job done right doesn't strike me as a high price to pay.

If there is not a way to set the clock speed, this is a missing feature which is important.

Whether or not there are "official" Arduino devices designed for minimal power use is irrelevant. If I am using an AVR chip (we have designed our own boards, which are slightly less than 1" in diameter), I don't have anything on the board consuming power other than the CPU chip. But it is an AVR chip, supported by the Arduino IDE.

I have a device that will measure actual power consumption over time (available from Digi-Key, Part #1490-NRF-PPK2-ND), so I will soon have live data.

Interesting, in that AVR processors have "light sleep" and "deep sleep" modes, clearly designed for power management, and techniques such as shutting down the ADCs during sleep, to reduce power consumption, and changing the clock speed, which reduces power consumption. So what did I miss about a processor that is "not designed for that"? Do you have a recommendation for one which is? Note that form factor is important, and most SMT packages will not work for various nontechnical, but critical, reasons.

Currently, the spreadsheet shows that the battery lifetime, with power management, will increase from 36 hours to about 14 months. We spend about 99.98% of the time sleeping. The only sensor that needs full power is the communications sensor, which, when a transmission starts, will wake up the CPU via an interrupt. Without the communications sensor, the battery life would be close to 4 years. The CPU needs to be on less than 1 second per hour.

1 Like

If low power / long battery life is your objective, see here for the definitive guide: https://www.gammon.com.au/power

You appear to have conflated low power consumption and low clock rate which is not always the case as has been pointed out.

If (on AVR systems) you change F_CPU to something other that the real crystal/oscillator value, you have the option of altering the pre-scaler to match so some functions (like millis() etc.) still work. Whether that brings you anything I don't know.

So how can the forum advise if the reason why 'most most SMT packages will not work' is not known ?

You missed what I said, the processor itself is not designed for a very low power consumption. Of course it has features that mitigate the power consumption but for real low power you have to switch to a processor that is specifically designed for it.

By suggesting a processor family and letting me find the right package.

But its low power modes seem adequate for our needs.

I'd have guessed soldering skills and eyesight and left it at that.

I dunno. The ATmega328p is a "Picopower" offering, designed to have very low power consumption. I haven't paid much attention to how competitive it has stayed with newer chips, but my general impression is that chips pretty much reached the stage where their power consumption (with suitable modes used/etc) was below the leakage current of most battery technology anyway (well, for GOOD batteries. Which would be another problem.)

The "modes" turn out to be really important, hard to measure, and even harder to predict between multiple CPU families. Newer AVR chips have "Core independent peripherals", which permit more to be done without waking the CPU from sleep modes - apparently that can improve overall power usage in many cases. But it's all a pretty black art - maybe just lowering the clock speed IS easiest, if it gets you the sort of battery lifetime that you're looking for.
(But I'd certainly be looking at the newer Mega-0 and "X-tiny" chips in the avr range, and maybe MSP430 (supported by "Energia") and ARM chips, as well as "classic" Uno chips (which are ~10y old now...))

Flounder, you've been coming here occasionally since 2014, complaining about how Arduino is missing some feature that you consider important, but no one else seems to care very much about. And neither the community nor the Arduino Company has been very sympathetic or helpful. You're clearly not the "target audience." Why haven't you switched to something else? (or, you know, written your own low-power core? I mean, really, you don't even want to have a 1ms clock-tick, do you?)

Or for or the sort of basic no-pwm, no-uart case where the only real timing-dependent bits are delay(), millis() and micros(), can't you just write your own wrapper functions that keep track of whether you've switched clock rates?

I have a device that will measure actual power consumption over time (available from Digi-Key, Part #1490-NRF-PPK2-ND)

Interesting. Microchip has a "Power Debugger" board as well (at over 2x the price of the Nordic board you reference.) I'd be interested in hearing how well the Nordic tool works with non-nordic chips.

exactly soldering skills and eyesight, but not mine; I have my own reflow oven.

1 Like

52 bytes to get the job done right doesn't strike me as a high price to pay.

If there is not a way to set the clock speed, this is a missing feature which is important.

Whether or not there are "official" Arduino devices designed for minimal power use is irrelevant. If I am using an AVR chip (we have designed our own boards, which are slightly less than 1" in diameter), I don't have anything on the board consuming power other than the CPU chip. But it is an AVR chip, supported by the Arduino IDE.

I have a device that will measure actual power consumption over time (available from Digi-Key, a Nordic Semiconductor NRF-PPK2). and should have some live data within the month.