SOLVED! ATMega328P at 14.7456 MHz

Hi!

As describe at the thread Help! High Speed RS485 Serial Software, I plan to use my Arduino as a slave connected to a 921 600 bauds RS485 master. I can't lower the 921 600 speed of the bus.

I bought a Breadboard Arduino Compatible Kit from oomlout and a 14.7456 MHz crystal, since 14 745 600 / 16 gives 921 600. The RS485 to serial converter is a SN65176B / SN75176B.

I experienced no problem to build the kit and it worked fine from the start with the supplied 16 MHz crystal.

I use the Arduino Serial USB Board sold by Sparkfun to upload the sketches, with the classic trick of a 0.1 uF capacitor between USB DTR and Arduino Reset pin for automatic reset.

Now, when I use the 14,7456 MHz crystal, I can't upload any sketch.

I updated the following files:

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/boards.txt

pro147.name=Arduino Board 5V 14,7456 MHz ATmega328

pro147.upload.protocol=stk500
pro147.upload.maximum_size=30720
pro147.upload.speed=57600

pro147.bootloader.low_fuses=0xFF
pro147.bootloader.high_fuses=0xDA
pro147.bootloader.extended_fuses=0x05
pro147.bootloader.path=atmega
pro147.bootloader.file=ATmegaBOOT_168_atmega328_14_7MHz.hex
pro147.bootloader.unlock_bits=0x3F
pro147.bootloader.lock_bits=0x0F

pro147.build.mcu=atmega328p
pro147.build.f_cpu=14745600L
pro147.build.core=arduino

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c around line 583

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
	while(bit_is_set(EECR,EEPE));			//Wait for previous EEPROM writes to complete
#else
	// while(bit_is_set(EECR,EEWE));			//Wait for previous EEPROM writes to complete
	while(!eeprom_is_ready());
	// http://arduino.cc/forum/index.php?action=printpage;topic=58154.0
	// Title: ATmegaBOOT_168.c bootloader does not compile with newer AVR tools
	// Post by: bperrybap on April 11, 2011, 02:26:42 AM
				
#endif

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/atmega/Makefile

##################################################################
#
# May 28, 2011
#
atmega328147: TARGET = atmega328_14_7MHz
atmega328147: MCU_TARGET = atmega328p
atmega328147: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
atmega328147: AVR_FREQ = 14745600L 
atmega328147: LDSECTION  = --section-start=.text=0x7800
atmega328147: $(PROGRAM)_atmega328_14_7MHz.hex

atmega328147_isp: atmega328
atmega328147_isp: TARGET = atmega328_14_7MHz
atmega328147_isp: MCU_TARGET = atmega328p
atmega328147_isp: HFUSE = DA
atmega328147_isp: LFUSE = FF
atmega328147_isp: EFUSE = 05
atmega328147_isp: isp

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

I burned the boot-loader thanks to the procedure Using an Arduino as an AVR ISP. Burning went fine.

Two problems:

  • Auto-reset doesn't work. However, uploading a sketch with a manual reset runs fine and is successful.
  • The standard blinking LED with 1 second on and 1 second off is slower than expected. It seems the 14.7456 MHz is ignored, even when I declare
    #define F_CPU        14745000L

So, two questions:

  • How to make the auto-reset working properly?
  • How to obtain the right speed in accordance to the 14.7456 MHz crystal?

Thank you for your help!

I will only talk about the bootloader/auto-reset part of your problem(s). The bootloader is hard coded to work at 16mhz for the specific upload baudrate specified in the boards.txt file. To change the bootloader to operate at the same baudrate now running at 14.7456 Mhz requires it be be recompiled with different baudrate values so as to work at the new clock frequency. This is not something you can do with the arduino IDE software.

EDIT: I see below that you are using a new/modified bootloader, so disregard my post. :wink:

Lefty

I read somewhere that SOMETHING in the Arduino is dependent on the processor speed being 1,000,000 * 2^^n (1MHz, 2MHz, 4MHz, 8MHz or 16MHz). This may be what you are running into. Maybe you can just ignore the problem is there aren't any critical delays in your code or you can shorten the delays to bring them back to spec.

johnwasser:
I read somewhere that SOMETHING in the Arduino is dependent on the processor speed being 1,000,000 * 2^^n (1MHz, 2MHz, 4MHz, 8MHz or 16MHz).

The interrupt service routine for timer 0 (millis, micros) requires a power-of-two clock speed.

At 14745600 Hz, the error is 0.64%. I think delay and delayMicroseconds integrate the error so "blink without delay" should give better results.

I see it now in wiring.h and wiring.c: The "clockCyclesPerMicrosecond" macro divides F_CPU by 1,000,000 (both integers). Then micros() function will return a time based on a 14MHz clock and, worse, will integer divide that '14' it into 64 which gives a value of 4, same as for a clock speed of 16MHz. The delay() function is based on the micros() clock so it, too, thinks the clock is running at 16MHz.

The delayMicroseconds() function is even worse. If F_CPU is not equal to 16000000L then it is ASSUMED to be 8 MHz.

After some research, I found a strange collection of low level header files

That would be "AVR Libc".

#define F_CPU 14745600L // This line is unnecessary. The Arduino IDE provides this definition for you. I suggest removing it.

#define BAUD 921600
#include <util/setbaud.h>
#include <util/delay.h>

Hello I'm very interested in this topic, because I plan to modify the crystal of one of my project to get fewer error with the serial transmission (cf. 14.7456 Mhz vs 16 Mhz)

Is there a kind of documented procedure somewhere ?

And did someone solved the problment with timing procedure (delay,micros,millis) ?

Sincerly
Sylvain

You might want to look at this old code/thread. I think at one time, the timer0 clock sir got made very general, but most of that seems to have disappeared for some reason... ( too complicated, even though it distilled to very little code?)

http://forum.arduino.cc/index.php?topic=37082.msg274217#msg274217