Go Down

Topic: Is there a simple way to reduce clock speed on an UNO? (Read 6501 times) previous topic - next topic

robtillaart

I have rewritten my DHT library recently and want to test it quickly on lower clock speeds - 8,4,2,1  MHz.

Is there an easy way to reduce the (effective)  clock speed?

I know it can be done by rewriting bootloader/fuses etc.

I've used a program on the PC once that could use X% of the clock cycles where X was configurable between 0..99
Could something like that be done with a timer and empty ISR (or nop filled ISR)

anyone experimented?



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Peter_n

#1
Oct 08, 2014, 07:22 pm Last Edit: Oct 08, 2014, 07:29 pm by Peter_n Reason: 1
You can use the clock prescaler, but a lot in the sketch will go wrong : millis(), Serial, and others.

In the datasheet : section 8.12.2, page 37, CLKPR.
I have used it on non-Arduino ATtiny chips.

hiduino

Yes, this can easily be done without make any hardware changes by adjusting the System Clock Prescaler.

This is what I have used on an Uno board.  First you need to create a custom boards.txt file.

In the \{skteches}\hardware\MyArduino\boards.txt.
Code: [Select]

##############################################################

Uno8.name=Arduino Uno (Prescale /2 - 8MHz)
Uno8.upload.protocol=arduino
Uno8.upload.maximum_size=32256
Uno8.upload.speed=115200
Uno8.bootloader.low_fuses=0xff
Uno8.bootloader.high_fuses=0xde
Uno8.bootloader.extended_fuses=0x05
Uno8.bootloader.path=optiboot
Uno8.bootloader.file=optiboot_atmega328.hex
Uno8.bootloader.unlock_bits=0x3F
Uno8.bootloader.lock_bits=0x0F
Uno8.build.mcu=atmega328p
Uno8.build.f_cpu=8000000L
Uno8.build.core=arduino:arduino
Uno8.build.variant=arduino:standard

##############################################################

Uno4.name=Arduino Uno (Prescale /4 - 4MHz)
Uno4.upload.protocol=arduino
Uno4.upload.maximum_size=32256
Uno4.upload.speed=115200
Uno4.bootloader.low_fuses=0xff
Uno4.bootloader.high_fuses=0xde
Uno4.bootloader.extended_fuses=0x05
Uno4.bootloader.path=optiboot
Uno4.bootloader.file=optiboot_atmega328.hex
Uno4.bootloader.unlock_bits=0x3F
Uno4.bootloader.lock_bits=0x0F
Uno4.build.mcu=atmega328p
Uno4.build.f_cpu=4000000L
Uno4.build.core=arduino:arduino
Uno4.build.variant=arduino:standard

##############################################################

Uno2.name=Arduino Uno (Prescale /8 - 2MHz)
Uno2.upload.protocol=arduino
Uno2.upload.maximum_size=32256
Uno2.upload.speed=115200
Uno2.bootloader.low_fuses=0xff
Uno2.bootloader.high_fuses=0xde
Uno2.bootloader.extended_fuses=0x05
Uno2.bootloader.path=optiboot
Uno2.bootloader.file=optiboot_atmega328.hex
Uno2.bootloader.unlock_bits=0x3F
Uno2.bootloader.lock_bits=0x0F
Uno2.build.mcu=atmega328p
Uno2.build.f_cpu=2000000L
Uno2.build.core=arduino:arduino
Uno2.build.variant=arduino:standard

##############################################################

Uno1.name=Arduino Uno (Prescale /16 - 1MHz)
Uno1.upload.protocol=arduino
Uno1.upload.maximum_size=32256
Uno1.upload.speed=115200
Uno1.bootloader.low_fuses=0xff
Uno1.bootloader.high_fuses=0xde
Uno1.bootloader.extended_fuses=0x05
Uno1.bootloader.path=optiboot
Uno1.bootloader.file=optiboot_atmega328.hex
Uno1.bootloader.unlock_bits=0x3F
Uno1.bootloader.lock_bits=0x0F
Uno1.build.mcu=atmega328p
Uno1.build.f_cpu=1000000L
Uno1.build.core=arduino:arduino
Uno1.build.variant=arduino:standard



Then in your sketch, add this at the top:
Code: [Select]

#include <avr/power.h>

void setup() {
  if(F_CPU == 8000000) clock_prescale_set(clock_div_2);
  if(F_CPU == 4000000) clock_prescale_set(clock_div_4);
  if(F_CPU == 2000000) clock_prescale_set(clock_div_8);
  if(F_CPU == 1000000) clock_prescale_set(clock_div_16);
}


The way this works is the Uno first boots up initially at 16MHz, so the default bootloader will work properly.  And you can do sketch uploads as normal.  But then your sketch is compiled at the prescaled clock rate, so when your sketch starts up the first thing is to adjust the clock prescale and then your code should execute at the correct speed.  Keep in mind depending on which core you use it may not have the support for some clock speeds.

robtillaart

@hiduino
Thanks!
works like a charm for  8Mhz - learned something today!

Do you have a version of

void delayMicroseconds(unsigned int us)    -   (wiring.c)

for 4, 2, and/or 1 MHz?

There is an #error not supported clockspeed.
fiddling with the 4Mhz gave some results but possibly you have a tuned version?



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Coding Badly


_delay_us may be a reasonable substitute.  It's part of Libc.  Be wary of the maximum delay time.

robtillaart

First  results my new version of DHT library @4 MHz
- http://forum.arduino.cc/index.php?topic=58531.msg1912859#msg1912859 -

dht22_test.ino
4000000
LIBRARY VERSION: 0.1.15

Type,   status,   Humidity (%),   Temperature (C)   Time (us)
DHT22,    21   Checksum error,   67.7,   21.2,   5600
DHT22,    14   OK,   66.1,   21.1,   5648
DHT22,    27   OK,   66.0,   21.1,   5616
DHT22,    26   OK,   65.9,   21.2,   5600
DHT22,    14   OK,   65.8,   21.2,   5536
DHT22,    14   OK,   65.6,   21.2,   5504
DHT22,    14   Time out error,   -999.0,   -999.0,   6880
DHT22,    27   OK,   65.4,   21.3,   5664
DHT22,    14   OK,   65.1,   21.3,   5600
DHT22,    15   OK,   64.9,   21.3,   5504
DHT22,    14   OK,   64.7,   21.3,   5696
DHT22,    26   OK,   64.6,   21.3,   5648
DHT22,    7   OK,   64.5,   21.3,   5520
DHT22,    26   OK,   64.4,   21.3,   5600
DHT22,    14   OK,   64.3,   21.3,   5616
DHT22,    14   OK,   64.3,   21.3,   5600
DHT22,    14   Checksum error,   115.5,   21.3,   5616
DHT22,    14   OK,   64.3,   21.3,   5600
DHT22,    14   OK,   64.3,   21.3,   5600
DHT22,    26   OK,   64.4,   21.3,   5600

TOT   OK   CRC   TO   UNK
20   17   2   1   0
....

DHT22,    19   OK,   66.2,   21.1,   5696
DHT22,    26   OK,   66.2,   21.1,   5696
DHT22,    14   Checksum error,   66.3,   225.9,   5712

TOT   OK   CRC   TO   UNK
100   82   12   6   0
....
TOT   OK   CRC   TO   UNK
200   166   25   9   0


Score of ~80% is not too bad
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

arduinoques

Would this work the same for the arduino nano? Can you state what differences I would need to make or provide code?

Thank you

Go Up