2
\$\begingroup\$

I know it's possible to change the clock prescaler at runtime. But is there a way to set the prescaler that is used at boot on an ATMega328? I'm aware of the fuses, but those are pretty permanent. I want it to start up at 8MHz and see if it's running on a lower voltage backup battery first. And if not, then switch to 16MHz. I've tried doing it as the first thing in setup() but it doesn't seem fast enough.

\$\endgroup\$
1
  • \$\begingroup\$ but, if you select a clock divide by 8, shouldn't F_CPU now be 2MHZ instead of 16MHZ? \$\endgroup\$
    – user51817
    Aug 22, 2014 at 9:49

1 Answer 1

3
\$\begingroup\$

I'm aware of the fuses, but those are pretty permanent

You can use the CLKDIV8 fuse, it only controls the preloaded cpu divider value so I don't consider it a permanent change.
The fuse sets the default loaded value to CLKPR (Clock prescale register) to either

  • clk/1
  • clk/8

Then in your code you can just set the divider to clk/1 to restore the cpu speed to 16MHz


I'm not sure but unless the bootloader is adaptive this change may affect the UART speed and create problems with the Arduino bootloader, this needs to be tested.


I did a test with my Arduino pro mini (m328p). After enabling the CLKDIV8 fuse using an external programmer, the Arduino bootloader becomes unresponsive and I don't see any way to override the UART speed that Arduiono IDE tries to use.


Updated Solution

I found another solution that doesn't need to change the bootloader, you just create a new profile for the board that has the CLDIV8 fuse enabled.

You need to modify the file boards.txt (e.g. arduino-1.5.5\hardware\arduino\avr\boards.txt), the baud rate for each board is stored there.

Locate the section that refers to your board, for example in my case

## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328
## -------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328 (5V, 16 MHz)

pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600

pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex

pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L

Now copy and paste that section to create a duplicate entry that we are going to modify. In that entry you'll have to change the name so that it doesn't conflict with the existing one (any new name will do), and set the baud rate to 1/8 of the one that was originally used.
I'm showing the changes in bold

enter image description here

The old entry with the new one following it look like this in my case:

## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328
## -------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328 (5V, 16 MHz)

pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600

pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex

pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L

## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328 CLKDIV8
## -------------------------------------------------
pro.menu.cpu.16MHzatmega328CLKDIV8=ATmega328 (5V, 16 MHz) CLKDIV8

pro.menu.cpu.16MHzatmega328CLKDIV8.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328CLKDIV8.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328CLKDIV8.upload.speed=7200

pro.menu.cpu.16MHzatmega328CLKDIV8.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328CLKDIV8.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328CLKDIV8.bootloader.extended_fuses=0x05
pro.menu.cpu.16MHzatmega328CLKDIV8.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex

pro.menu.cpu.16MHzatmega328CLKDIV8.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328CLKDIV8.build.f_cpu=16000000L

After saving the file you'll see a new entry in Arduino IDE, by using it you will be able to program the modified board.

enter image description here

enter image description here

\$\endgroup\$
13
  • \$\begingroup\$ @adamhaile unfortunately changing the fuse will make Arduino bootloader unresponsive, this can only be used with an external programmer. \$\endgroup\$
    – alexan_e
    Mar 9, 2014 at 0:44
  • \$\begingroup\$ hahaha... was just testing that myself. and yup... no go. darn :( \$\endgroup\$
    – Adam Haile
    Mar 9, 2014 at 0:48
  • \$\begingroup\$ @AdamHaile I also tried with xLoader that has the option to set the UART speed. I used 7200 but it didn't work either (1/8 of 57600). \$\endgroup\$
    – alexan_e
    Mar 9, 2014 at 0:54
  • 1
    \$\begingroup\$ The trick is to use a modified boot loader that is configured to generate the expected baud rate from the initial fuses. \$\endgroup\$
    – mpflaga
    Mar 9, 2014 at 1:48
  • \$\begingroup\$ @AdamHaile I found a solution, read the updated answer \$\endgroup\$
    – alexan_e
    Mar 9, 2014 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.