I'm working on a custom arduino that will run at 3.3 V with no regulators or USB chips (for power consumption). I've heard that overclocking the chip at 16 MHz/3.3 V is generally fine, but I'd like to stay within spec anyway.

First: to run at 8 MHz, do I just need to replace the crystal? Or is there anything else I have to do?

Second: Do I need to make any code changes to reflect the new speed? I'm using serial, SPI, and I2C connections in this project, along with the NilRTOS operating system and millis/delay functions. Will any of these be broken? Will the code run noticeably slower?

Third: How can I program the chip? Is it ok to program it in an Arduino Uno at 16 MHz, then transplant it to the custom arduino?

Fourth: Will power consumption change at 8 MHz?

Thanks!

  • 2
    There are plenty of 3.3V Arduino-compatible boards, Sparkfun Pro mini being one example. It is supported by the IDE so all clock-specific adjustments will be made for you once you pick it from the 'boards' dropdown. – Oleg Mazurov Feb 18 '15 at 23:37
  • At 8MHz you'll probably be okay using the internal oscillator instead of a crystal. Beware when you compile code that when you for example pick "Pro Mini 328p at 8MHz" that 8 gets applied to code, so I wouldn't suggest compiling for 16MHz and then transplanting or you may find that a delay(1000) takes two seconds as a simple example. And check out power saving/sleep in the H2OhNo code. (Another moment when I suggest you get any programmer at all instead of limiting yourself to serial uploads, search Tindie for "ISP.") – Patrick Tudor Feb 23 '15 at 2:28
up vote 7 down vote accepted

The formula seems to be volt*5.9-6.6=mhz (valid between 1.8v and 4.5v), so at 3.3v, this would give 12.8mhz. Be aware that, if you are running at 12.8mhz, ANY drop below 3.3v MAY cause problems (and very hard to diagnose, too!) or you MAY get away with it.

However, Arduino Atmega328p chips have a "brown-out" detection set at 4.3v - any drop below that, the chip shuts down. You can get an ISP (AKA ICSP) to change the fuses - go to http://www.engbedded.com/fusecalc/ to work out what to set fuses to. You can also use the ISP to read the current fuses, or indeed reprogram the chip without an Arduino board - all my projects have a 6-pin header. If you do this, before reprogramming using the Arduino board, you will have to "Burn Bootloader" (in the tools menu). Note that programming can still be done via Arduino IDE.

Alternatively, if you want to go "light" (and have an ISP), you can change the fuses to use the internal 8mhz clock - this frees up 2 extra pins, too! Be aware, however, that the internal clock may drift 1.2 hours per day (=5%), compared to 1.7 seconds per day (=20 parts per million) on a typical quartz crystal. If you don't use it for timekeeping, this probably doesn't matter.

You will need to make changes to the timing, for your code - you need to add a boards.txt with correct settings for your chip/clockspeed etc - you can copy the settings from the entry for the board, change the name, and change the setting "build.f_cpu"; restart (or start) your Arduino IDE, go to "Tools->Board" and select the board you added.

You can move the chip on/off the board, and reprogram it there (note that the board selected in Tools->Board is the FINAL board, not the programming board). Be careful plugging/unplugging it - eventually, you WILL bend the pins! Alternatively, you can use ISP (ICSP), as mentioned above - much recommended. ISP programming will also work if the chip is factory default, so long as it has a working clock.

How much power is used by the chip depends hugely on what you do with it - not just clock speeds, clock source, etc but also sleep modes. If you are sleeping a lot, it may draw less when running faster than running slower - if almost all your time is asleep, then the power consumption should be counted per clock cycle, not per second - if your clock is half the speed, and half current, then you draw the same current per instruction. Since the rest of your time is spent asleep, you get no benefit. See http://www.gammon.com.au/power for a very good breakdown of power usage, tips on how to save power, etc.

If you slow your clock down too much, serial and i2c may become unreliable (unless you slow down the speed), but I would expect to be able to go down to 1mhz before this to be a problem - a 1mhz chip trying to do 9600bps has 104 instructions per bit of data transferred. i2c runs at 100khz, so you get 10 instructions per bit (at 1mhz) - possibly pushing it. 8mhz should be fine. Test, test, test.

UPDATE: There are 3 possible settings for the brown-out detection - there are 3 possible values for the AtMega328p: disabled, 1.8v, 2.7v, and 4.3v. I was under the impression (above) that Arduinos were normally set to 4.3v; apparently that is not the case (see comment below). I recall seeing somewhere that there was brownout detection. This is something to keep in mind, if your arduino resets, especially when putting larger loads on the battery (running motors, multiple leds etc).

  • Thanks for this response! I'm a bit baffled by what you said about the brownout detector shutting down below 4.3 V. I'm running at 3.7 V now and it works fine; didn't have to make any changes to the fuses. – Vulcan Feb 19 '15 at 20:22
  • @user40, see "UPDATE" section at the bottom of my post. – AMADANON Inc. Feb 22 '15 at 20:35

First: to run at 8 MHz, do I just need to replace the crystal? Or is there anything else I have to do?

No, run on the internal oscillator as suggested by AMADANON Inc.

Alternatively, set the "divide clock by 8" fuse (which would run it at 2 MHz from a 16 MHz crystal) and then in code change the division back up to 2. ie.

#include <avr/power.h>

void setup ()
  {
  // slow clock to divide by 2
  clock_prescale_set (clock_div_2);
  } // end of setup

Or for programming in another Uno leave the fuse alone, program at 16 MHz and then drop the clock down in the target chip, hoping it works long enough at 3.3V to execute that first instruction. The safest thing would be to just install an 8 MHz crystal or resonator on the target board. However if timing is not critical run with the internal oscillator.

Second: Do I need to make any code changes to reflect the new speed? I'm using serial, SPI, and I2C connections in this project, along with the NilRTOS operating system and millis/delay functions.

If you tell the IDE you have an 8 MHz processor (eg. a Lilypad) then it should adjust delays, baud rate calculations etc. appropriately.

Will any of these be broken?

I2C and SPI are self-clocked. They can run at a variety of rates. I doubt there will be any problems with them. As for serial, providing the calculations are done right a wide range of baud rates should still be available.

Will the code run noticeably slower?

Well yes, it will run at half speed compared to 16 MHz.

Third: How can I program the chip? Is it ok to program it in an Arduino Uno at 16 MHz, then transplant it to the custom arduino?

You can do that. Or you could connect up an ICSP header or an FTDI header and program it in situ.

Examples here: http://www.gammon.com.au/breadboard

Fourth: Will power consumption change at 8 MHz?

Yes, it is reduced somewhat.

You can reduce it considerably more by using other techniques as described at http://www.gammon.com.au/power, and referred to by AMADANON Inc.

  • Thanks Nick! I've actually read your website before and it helped me cut my power consumption radically. As a result, AAs and AAAs are now a viable power source for this device, which is a big deal because weight matters. So thanks for that website too--it's a huge service to the community and really helpful to people like me. – Vulcan Jun 27 '15 at 4:48

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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