Go Down

Topic: 8MHz internal oscillator: success! (Read 60019 times) previous topic - next topic

tylernt

This isn't a cry for help, it's a success story. :)

So, I've been intensely studying Arduino for the last couple weeks ever since I had a project in mind that needed one (automatic chicken coop door). Since my application will be solar powered, I didn't want an onboard USB-serial power hog so I'm making my own PCB (using perfboard, actually). I also decided to use the internal oscillator for this project because... well, just because I could. Now, I know the internal osc. isn't super accurate, but that doesn't matter for a lot of projects. But wait you say, what about serial communications, like uploading sketches? Well yeah, the default 57,600 bit rate isn't very reliable without a good clock, but http://www.wormfood.net/avrbaudcalc.php shows that 38,400 is still pretty fast, yet has a much better chance of success @ 8MHz. And in my case, it was indeed successful.

So, here's the recipe for anyone else who wants to either save 50¢, simplify their project, or free up two more GPIO pins:

Step one is to go into arduino-1.0.1\hardware\arduino\bootloaders\optiboot and edit the 'Makefile' file with your favorite text editor. Go down the standard atmega328 section and below it paste in:

Code: [Select]

# Standard atmega328, only at 38,400 baud for closer clock accuracy AND using 8Mhz internal RC oscillator
#
atmega328_384_8: TARGET = atmega328
atmega328_384_8: MCU_TARGET = atmega328p
atmega328_384_8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega328_384_8: AVR_FREQ = 8000000L
atmega328_384_8: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_384_8: $(PROGRAM)_atmega328_384_8.hex
atmega328_384_8: $(PROGRAM)_atmega328_384_8.lst

atmega328_384_8_isp: atmega328
atmega328_384_8_isp: TARGET = atmega328
atmega328_384_8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_384_8_isp: HFUSE = DE
# Int. RC Osc. 8MHz, slowly rising power-65ms
atmega328_384_8_isp: LFUSE = E2
# 2.7V brownout
atmega328_384_8_isp: EFUSE = 05
atmega328_384_8_isp: isp


(To get these fuse settings, I used http://www.engbedded.com/fusecalc/)

Then go to a command prompt and change to the arduino-1.0.1\hardware\arduino\bootloaders\optiboot folder and issue

Code: [Select]

omake atmega328_384_8


This will fail, because optiboot.c has a bug. Fortunately, the bug was fixed -- just grab the patched code from http://code.google.com/p/optiboot/source/browse/optiboot/bootloaders/optiboot/optiboot.c?spec=svn5ec3f2030308441365fe4e9aebf7ebeb8939fae8&r=5ec3f2030308441365fe4e9aebf7ebeb8939fae8 and then you can proceed to run the command again to compile your custom bootloader.

Now go into arduino-1.0.1\hardware\arduino and edit boards.txt. Add an entry like this:

Code: [Select]

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

atmega328_384_8.name=ATmega328 Optiboot @ 38,400baud w/ 8MHz Int. RC Osc.

atmega328_384_8.upload.protocol=arduino
atmega328_384_8.upload.maximum_size=30720
atmega328_384_8.upload.speed=38400

atmega328_384_8.bootloader.low_fuses=0xE2
atmega328_384_8.bootloader.high_fuses=0xDE
atmega328_384_8.bootloader.extended_fuses=0x05
atmega328_384_8.bootloader.path=optiboot
atmega328_384_8.bootloader.file=optiboot_atmega328_384_8.hex
atmega328_384_8.bootloader.unlock_bits=0x3F
atmega328_384_8.bootloader.lock_bits=0x0F

atmega328_384_8.build.mcu=atmega328p
atmega328_384_8.build.f_cpu=8000000L
atmega328_384_8.build.core=arduino
atmega328_384_8.build.variant=standard


Now you can proceed to use your ISP (I used a second Atmega328 as ISP, but whatever) to burn this bootloader onto your chip. Note, if you're changing the bootloader on a chip that previously was configured to use an external clock, you'll need to have that external clock hooked up during the first bootloader burn.

Of course, I realize that using the internal RC oscillator is kind of iffy. Clock speed will fluctuate with changing VCC and temperature. If more accuracy is desired, the next phase would be to calibrate each chip individually and add a couple lines of code to optiboot to apply a different custom OSCCAL to each one. However I'm guessing that even without this, using baud rates like 38400, 19200, or 9600 will serve many asynchronous serial applications adequately.

I'll admit I'm an Arduino noob, so feel free to tear me apart now. ;)

Osgeld

I tend to think that most people overate their serial needs,I even encountered it at the lab, using a device clocking in at 9600

"that's awful slow"

"OMG its sending 3 bytes, are you really going to notice it?"
http://arduino.cc/forum/index.php?action=unread;boards=2,3,4,5,67,6,7,8,9,10,11,66,12,13,15,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,86,87,89,1;ALL

bubulindo

I used it before on an ATmega8 with heavy serial port needs... No problems whatsoever. This was almost ten years ago too, not sure if the internal oscillator in AVRs has changed much lately.

You can now use the oscillator pins as a RTC and save the external chip.
I'm testing it out on an old ATmega16, and maybe create a library if it works out ok.

Good work.
This... is a hobby.

Christo


This will fail, because optiboot.c has a bug. Fortunately, the bug was fixed -- just grab the patched code from http://code.google.com/p/optiboot/source/browse/optiboot/bootloaders/optiboot/optiboot.c?spec=svn5ec3f2030308441365fe4e9aebf7ebeb8939fae8&r=5ec3f2030308441365fe4e9aebf7ebeb8939fae8 and then you can proceed to run the command again to compile your custom bootloader.


Thanks for sharing tylernt.  I ran into this bug when trying to compile optiboot for low baud rates.

Robofarmer

Want to start a chicken coop mod club? I got into microcontrollers specifically because of the possibility of automating my coop.

dhenry

Quote
but http://www.wormfood.net/avrbaudcalc.php shows that 38,400 is still pretty fast, yet has a much better chance of success @ 8MHz.


That pages shows the theoretical error due to the BR generate being discrete.

My experience is that the uart isn't very reliable, with the internal oscillator,  at 19200bps or higher (more than 10% errors - transmitted data is not the same as the data sent.) but 9600bps or lower it is fairly reliable.

tylernt


Want to start a chicken coop mod club? I got into microcontrollers specifically because of the possibility of automating my coop.
Automating coops does seem to be a very popular project. I don't think we have a dedicated section but if you do a search on this site, lots of things come up.

My experience is that the uart isn't very reliable, with the internal oscillator,  at 19200bps or higher (more than 10% errors - transmitted data is not the same as the data sent.) but 9600bps or lower it is fairly reliable.
Hm. I admit I haven't used it much, just printing debug info from my sketches, but haven't noticed garbage characters so far. But this may vary from chip to chip and maybe I just lucked out on a good one.

Also I upload all my sketches at 38400, but perhaps avrdude has automatic checksum/retransmission as part of it's protocol so serial errors aren't harmful?

dhenry

It is fairly easy to test: write a pc program that receives a known string (I used a 40-char buffer). Count the correct strings and incorrect strings. You can also vary the temperature (use a hair dryer for example, or a coldpack on the mcu and see if the error rate changes).

9600bps is the practical limit, in my experience.

tylernt

Ah, I forgot about temperature. I've just been using mine at room temp. Good point.

Coding Badly

But this may vary from chip to chip...


It does.

Quote
...and maybe I just lucked out on a good one.


Probably.

They can be fairly easily tuned (OSCCAL register).

Quote
Also I upload all my sketches at 38400, but perhaps avrdude has automatic checksum/retransmission as part of it's protocol so serial errors aren't harmful?


Nope.  There is an optional verify pass but no checksum.

cowger

tylernt -- you are my hero!!!!  I've been battling this same issue for days, now, and you just got me *finally* up and running!!!

You da man!!!!!    :)

Thank you....

tylernt


Sheepslayer

Can anyone post the the .hex file? Mine will not compile

cabecinhas

This isn't a cry for help, it's a success story. :)

So, I've been intensely studying Arduino for the last couple weeks ever since I had a project in mind that needed one (automatic chicken coop door). Since my application will be solar powered, I didn't want an onboard USB-serial power hog so I'm making my own PCB (using perfboard, actually). I also decided to use the internal oscillator for this project because... well, just because I could. Now, I know the internal osc. isn't super accurate, but that doesn't matter for a lot of projects. But wait you say, what about serial communications, like uploading sketches? Well yeah, the default 57,600 bit rate isn't very reliable without a good clock, but http://www.wormfood.net/avrbaudcalc.php shows that 38,400 is still pretty fast, yet has a much better chance of success @ 8MHz. And in my case, it was indeed successful.

So, here's the recipe for anyone else who wants to either save 50¢, simplify their project, or free up two more GPIO pins:

Step one is to go into arduino-1.0.1\hardware\arduino\bootloaders\optiboot and edit the 'Makefile' file with your favorite text editor. Go down the standard atmega328 section and below it paste in:

Code: [Select]

# Standard atmega328, only at 38,400 baud for closer clock accuracy AND using 8Mhz internal RC oscillator
#
atmega328_384_8: TARGET = atmega328
atmega328_384_8: MCU_TARGET = atmega328p
atmega328_384_8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
atmega328_384_8: AVR_FREQ = 8000000L
atmega328_384_8: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_384_8: $(PROGRAM)_atmega328_384_8.hex
atmega328_384_8: $(PROGRAM)_atmega328_384_8.lst

atmega328_384_8_isp: atmega328
atmega328_384_8_isp: TARGET = atmega328
atmega328_384_8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_384_8_isp: HFUSE = DE
# Int. RC Osc. 8MHz, slowly rising power-65ms
atmega328_384_8_isp: LFUSE = E2
# 2.7V brownout
atmega328_384_8_isp: EFUSE = 05
atmega328_384_8_isp: isp


(To get these fuse settings, I used http://www.engbedded.com/fusecalc/)

Then go to a command prompt and change to the arduino-1.0.1\hardware\arduino\bootloaders\optiboot folder and issue

Code: [Select]

omake atmega328_384_8


This will fail, because optiboot.c has a bug. Fortunately, the bug was fixed -- just grab the patched code from http://code.google.com/p/optiboot/source/browse/optiboot/bootloaders/optiboot/optiboot.c?spec=svn5ec3f2030308441365fe4e9aebf7ebeb8939fae8&r=5ec3f2030308441365fe4e9aebf7ebeb8939fae8 and then you can proceed to run the command again to compile your custom bootloader.

Now go into arduino-1.0.1\hardware\arduino and edit boards.txt. Add an entry like this:

Code: [Select]

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

atmega328_384_8.name=ATmega328 Optiboot @ 38,400baud w/ 8MHz Int. RC Osc.

atmega328_384_8.upload.protocol=arduino
atmega328_384_8.upload.maximum_size=30720
atmega328_384_8.upload.speed=38400

atmega328_384_8.bootloader.low_fuses=0xE2
atmega328_384_8.bootloader.high_fuses=0xDE
atmega328_384_8.bootloader.extended_fuses=0x05
atmega328_384_8.bootloader.path=optiboot
atmega328_384_8.bootloader.file=optiboot_atmega328_384_8.hex
atmega328_384_8.bootloader.unlock_bits=0x3F
atmega328_384_8.bootloader.lock_bits=0x0F

atmega328_384_8.build.mcu=atmega328p
atmega328_384_8.build.f_cpu=8000000L
atmega328_384_8.build.core=arduino
atmega328_384_8.build.variant=standard


Now you can proceed to use your ISP (I used a second Atmega328 as ISP, but whatever) to burn this bootloader onto your chip. Note, if you're changing the bootloader on a chip that previously was configured to use an external clock, you'll need to have that external clock hooked up during the first bootloader burn.

Of course, I realize that using the internal RC oscillator is kind of iffy. Clock speed will fluctuate with changing VCC and temperature. If more accuracy is desired, the next phase would be to calibrate each chip individually and add a couple lines of code to optiboot to apply a different custom OSCCAL to each one. However I'm guessing that even without this, using baud rates like 38400, 19200, or 9600 will serve many asynchronous serial applications adequately.

I'll admit I'm an Arduino noob, so feel free to tear me apart now. ;)
Hello there.. I have done everything you said.. and created the optiboot_atmega328_384_8.hex etc...

But when I open the Arduino IDE and open de serial Monitor it burns the bootloader but no the one I selected on TOOLS > BOARDS.. It always burn the optiboot_atmega328.hex and no the optiboot_atmega328_384_8.hex.. how can I change it?

tks a lot


pito

#14
Mar 17, 2015, 08:29 pm Last Edit: Mar 17, 2015, 08:32 pm by pito
fyi
http://forum.arduino.cc/index.php?topic=61501.0

With oscal you may tune the internal oscillator from 5-15MHz (at least with my chips).
Be aware - without calibration your clock could be easily 20% off, bad for your uart's baudrate.. ;(
(as the 8MHz is tuned for 3.0V at factory).

Go Up