Arduino Pt.3

ATmega 8 / 168 internal clock and fuse settings

Considering the already low price of the Arduino board, building an Arduino-like board yourself probably doesn’t save you any money but is certainly a fun and education project to do.
I tried to make the simple board even simpler, by using a Serial instead of an USB Port, the ATmega’s internal clock instead of an external crystal, and requiring 5 VDC instead of providing any kind of power regulation. However, my board does expose the 6 header ICSP, equivalent to the one available on the original Arduino NG Board.
RadioShack’s Multipurpose 417 Holes $1.79 PC Board (Model: 276-150 Catalog: 276-150) built a great starting point for this electronics project, which was obviously inspired by Tom Igoe’s ‘Arduino Breadboard‘.

After soldering the components onto the board and checking all joints, it was time to put the Arduino bootloader into the Flash Ram, which raised a couple system / software related questions I hadn’t thought much about before:

  • To be able to use either the ATmega8, which is used on the original Arduino, or the pin compatible ATmega168 microcontroller, which offers twice the amount of internal RAM, I had put a 28-Pin DIP Socket on the board. While the original Arduino board uses an 16.0MHz external crystal, my board relies on the internal clock, which for the ATmega8 means a 1.0MHz Internal RC Oscillator (slowly rising power) and for the ATmega168 an 8.0MHz internal RC oscillator, which by default however gets divided by 8, resulting in 1.0MHz system clock. How could I address the speed difference, to keep software changes to a minimum?
  • Since this obviously involved messing with the ATmega’s confusing fuse settings, what fuse bits do I have to adjust?

Let’s address the last question first and take a look at the fuse bytes. The content of those fuse bytes persists reprogramming of the Flash memory and almost every bit in those fuse bytes represent some kind of status setting that configures the microcontroller, for instance to work in concert with other components on the board. Oddly enough, for all fuses ‘1’ means unprogrammed while ‘0’ means programmed.

ATmega’s con- fus(e) -ing settings

ATmega8 Fuse High Byte
Bit Name Description Default (0xD9) Custom Arduino (0xCA)
7 RSTDISBL Select if PC6 is I/O pin or RESET pin 1 (unprogrammed PC6 is RESET-pin) 1
6 WDTON WDT always on 1 (unprogrammed, WDT enabled by WDTCR) 1
5 SPIEN Enable Serial Program and Data Downloading 0 (programmed, SPI programming enabled) 0
4 CKOPT Oscillator options 1 (unprogrammed) 0
3 EESAVE EEPROM memory is preserved through the Chip Erase 1 (unprogrammed, EEPROM not preserved) 1
2 BOOTSZ1 Select Boot Size 0 (programmed) 0
1 BOOTSZ0 Select Boot Size 0 (programmed) 1
0 BOOTRST Select Reset Vector 1 (unprogrammed) 0
ATmega8 Fuse Low Byte
Bit Name Description Default (0xE1) Custom Arduino (0xDF)
7 BODLEVEL Brown out detector trigger level 1 (unprogrammed) 1
6 BODEN Brown out detector enable 1 (unprogrammed, no BOD) 1
5 SUT1 Select start-up time 1 (unprogrammed) 0
4 SUT0 Select start-up time 0 (programmed) 1
3 CKSEL3 Select Clock source 0 (programmed) 1
2 CKSEL2 Select Clock source 0 (programmed) 1
1 CKSEL1 Select Clock source 0 (programmed) 1
0 CKSEL0 Select Clock source 1 (unprogrammed) 1

Looking at my slightly reconfigured Arduino board, I chose the following fuse settings:
High Fuse: 0xDA and Low Fuse: 0xD1, which leaves the ATmega’s Oscillator options at their defaults while allowing the use of the EEPROM and also sets the boot size and boot vector like needed for the Arduino bootloader.

This brings me back to the other question:

How to address the speed difference, to keep software changes to a minimum?

The frequency the ATmega chip is running at, is hardcoded into the bootloader (ATmegaBOOT.c or ATmegaBOOT_168.c). While it is a configuration parameter in the Makefile, putting a bootloader on an Arduino-like board that does not run at 16.0MHz requires adjusting the Makefile and rebuilding the bootloader.
The best place to get Makefile and bootloader source for the ATMega8 is http://svn.berlios.de/viewcvs/arduino/trunk/bootloader/ the same for the ATmega168 can be found here: http://webzone.k3.mah.se/projects/arduino-workshop/upload/default.asp?folder=40

The ATmega8’s Makefile defines DEFS= -DF_CPU=16000000 -DBAUD_RATE=19200 which needs to be modified to DEFS= -DF_CPU=1000000 -DBAUD_RATE=19200
For the ATmega168, make needs to be called with the proper command-line parameters: make PRODUCT=CRUMB168 AVR_FREQ=F1000000 all

The last thing that needs to be done is adjusting the Arduino IDE preferences file: ~/Library/Arduino/preferences.txt on the Mac andC:\Documents and Settings\<USERNAME>\Application Data\Arduino\preferences.txt on Windows:
The build.f_cpu preference needs to be set to 1000000L

For completeness, here are the ATmega 168 fuse bytes, (a couple bits more a.k.a. ‘Extended Fuse Byte’, compared to the ATmega 8).

ATmega168 Extended Fuse Byte
Bit Name Description Default Custom Arduino
7..3 not used N/A 1 1
2 BOOTSZ1 Select Boot Size 0 (default value of BOOTSZ1..0 results in max. Boot Size 0
1 BOOTSZ0 Select Boot Size 0 (default value of BOOTSZ1..0 results in max. Boot Size 0
0 BOOTRST Select Reset Vector 1 (unprogrammed) 0
ATmega168 Fuse High Byte
Bit Name Description Default Custom Arduino
7 RSTDISBL External Reset Disable 1 (unprogrammed PC6 is RESET-pin) 1
6 DWEN debugWIRE Enable 1 (unprogrammed) 1
5 SPIEN Enable Serial Program and Data Downloading 0 (programmed, SPI programming enabled) 0
4 WDTON Watchdog Timer Always On 1 (unprogrammed) 1
3 EESAVE EEPROM memory is preserved through the Chip Erase 1 (unprogrammed, EEPROM not preserved) 0
2 BODLEVEL2 Brown out detector trigger level 1 (unprogrammed) 1
1 BODLEVEL1 Brown out detector trigger level 1 (unprogrammed) 1
0 BODLEVEL0 Brown out detector trigger level 1 (unprogrammed) 1
ATmega168 Fuse Low Byte
Bit Name Description Default Custom Arduino
7 CKDIV8 Divide clock by 8 0 (programmed) 1
6 CKOUT Clock output on PORTB0 1 (unprogrammed) 1
5 SUT1 Select start-up time 1 (unprogrammed) 0
4 SUT0 Select start-up time 0 (programmed) 0
3 CKSEL3 Select Clock source, default for CKSEL3..0 results in intern. 8MHz Oscillator 0 (programmed) 0
2 CKSEL2 Select Clock source 0 (programmed) 1
1 CKSEL1 Select Clock source 1 (unprogrammed) 1
0 CKSEL0 Select Clock source 0 (programmed) 1

Resources

Leave a Reply