Using Arduino IDE with Atmega328 @ 20Mhz

Hi!

I'm planning a game project that would output a color VGA signal. I would really like to get a few more pixels per scanline so I'm thinking of building a standalone board with a Atmega328 clocked at 20Mhz. Would it still be possible to use the Arduino IDE for development, or do I have to move to Atmel Studio (which I have no experience with)?

My understanding is that the default Optiboot bootloader does not work at 20Mhz, am I right? If bootloading is not an option, what is the next best thing? ISP programmer? I like to be able to iterate and test quickly by uploading code with the bootloader. I have no experience with ISP programmers, how is the workflow compared to using a bootloader?

Any advice is welcome, many thanks in advance!

ps. I prefer the challenge so I'm not interested in using an Arduino Due :)

If you run an ATmega328P at 20 MHz you can upload it with an ISP but the timers will be off. The millis(), micros(), delay() and delayMicroseconds() are designed to run properly only at a very limited number of frequencies (basically 8 MHz and 16 MHz). If you don’t rely on those functions or libraries that rely on those functions you should be OK.

In theory you can even compile a version of Optiboot for 20 MHz and upload using that.

Yes, the easiest way is to use the IDE file option of "upload using programmer" and then get one of the six different 'hardware programmers' that the IDE supports directly (it can be another arduino board running the arduinoISP sketch, or a $5 USBasp e-bay programmer) then connect the programmer to the target ISP pins, select the target board type, select the programmer type and then use the menu file option 'upload using programmer'.

If you wish to maintain timing accuracy for millis() and micros() and serial baudrates selections then you can go into the IDE core file, boards.txt, and edit the board entry you will be using from (assuming a uno board): and change: uno.build.f_cpu=16000000L to uno.build.f_cpu=20000000L

Lefty

Thanks for the info, guys! Using an ISP sounds good. I’ll probably order the DIY USBasp kit then (http://www.fundf.net/usbasp/). It’s more expensive than the prebuilt ebay programmers but I enjoy soldering and I want to support the authors :slight_smile:

Is there any gotchas with the ISP though? Reading the docs at the USBasp site leads me to believe that the firmware does not support serial transmission. Do I need a separate USB<->serial adapter for debugging? Or how do you debug code when using an ISP? (actually I’m not even sure if the serial library works at 20Mhz…hmmm…)

ph77:
Thanks for the info, guys! Using an ISP sounds good. I’ll probably order the DIY USBasp kit then (http://www.fundf.net/usbasp/). It’s more expensive than the prebuilt ebay programmers but I enjoy soldering and I want to support the authors :slight_smile:

Is there any gotchas with the ISP though? Reading the docs at the USBasp site leads me to believe that the firmware does not support serial transmission.
No serial support through the ISP programmer.

Do I need a separate USB<->serial adapter for debugging?
Yes. There are very inexpensive E-bay USB TTL serial adapters based that can work.

Or how do you debug code when using an ISP? (actually I’m not even sure if the serial library works at 20Mhz…hmmm…)
Should work if you correct the clock speed parameter I showed earlier in the board entry of the IDE’s boards.txt file.

retrolefty: If you wish to maintain timing accuracy for millis() and micros() and serial baudrates selections then you can go into the IDE core file, boards.txt, and edit the board entry you will be using from (assuming a uno board): and change: uno.build.f_cpu=16000000L to uno.build.f_cpu=20000000L

Unfortunately that won't fix the code in wiring.c that relies on (MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) being divisible by 8.

MICROSECONDS_PER_TIMER0_OVERFLOW is clockCyclesToMicroseconds(256*64) 256*64 = 16384

In Arduino.h:

define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )

So: 8 for 8MHz, 16 for 16 MHz and 20 for 20 MHz

In Arduino.h:

define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )

So MICROSECONDS_PER_TIMER0_OVERFLOW: 8 MHz = 2048 That's 2 milliseconds + 48 microseconds 16 MHz = 1024 That's 1 millisecond + 24 microseconds 20 MHz = 819.2 That's 0 milliseconds + 819 microseconds

The microseconds portion is divided by 8 so the counter will fit in a byte. Each time the timer overflows the extra microseconds are accumulated in a byte and when they reach 125 (1000/8) another millisecond is counted.

819 / 8 = 102.375. Every 819.2 microseconds the overflow counter will be incremented by 102 and a millisecond will be counted when it exceeds 125. That's every 1.2254901... overflows or every 1003.921 microseconds. Almost 0.4% slow but I guess that's not too bad.

Really. You can't just set F_CPU and expect the arduino timing functions to work.

The GOOD news is that delayMicroseconds() will work as of V1.0. Someone addd code for the 20 MHz case. Previously there was only code for 8 MHz and 16 MHz. If your F_CPU is not 20000000 or 16000000 it is assumed to be 8000000.