For the past week I’ve been debugging hardware and software to get my barebones ATmega328P to work with a 32.768kHz oscillator as Timer 2, which will tick outside of the sleeping microcontroller. This way I can keep track of time even as the microcontroller is off and saving power.
To get the 32.kHz clock to work was challenging, because I forgot some minor aspects of how to set the circuit up.
I ended up asking some questions on the Arduino Stack Exchange to really understand what I was doing and should do.
I wanted to test out Nick Gammon’s code, so I set up his example circuit:
But it was still dorking out. The LED wasn’t turning on and off like I programmed it to do when waking up from sleep, and sporadically it would turn on really brightly, then off. Reaaaally weird behavior.
I took to UTW to ask about my problem, and as silly as it sounds, it turns out I forgot to program the microcontroller to use the 8MHz internal oscillator for the programmer!
Originally, the arduino bootloader has the fuse byte settings to use an external 16MHz clock. I needed to use the 8MHz internal clock for the processor. derp.
So, back to the drawing board of setting up fuse bytes by reprogramming the bootloader.
The circuit can be found in my previous posts: ATMega328P Burning the Bootloader
I ran into so many errors. All the following comes from my engineering log on GitHub:
I’m using the Arduino UNO to serially program the fuse bytes.
I ran:
avrdude -c arduino -p m328p -P /dev/ttyACM0 -v -U lfuse:r:h
which outputted this:
Using Port : /dev/ttyACM0
Using Programmer : arduino
AVR Part : ATmega328P
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC
RESET disposition : dedicate
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Programmer Type : Arduino
Description : Arduino
Hardware Version: 3
Firmware Version: 4.4
Vtarget : 0.3 V
Varef : 0.3 V
Oscillator : 28.800 kHz
SCK period : 3.3 us
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f
avrdude: Expected signature for ATmega328P is 1E 95 14
Double check chip, or use -F to override this check.
avrdude done. Thank you.
Alright, so looks like 0x0f vs 0x14 is messing up the reading of the device… which is strange.
One answer from researching suggested to changed the baud rate.
"The thing that determines which you "talk to" is the baud rate. I believe that when you attempt to use ArduinoISP you need "-b 19200" in your avrdude command so it won't interact with the bootloader (Optiboot uses 115200 I think)."
I added “-b 19200” into my avrdude command, which produced the error:
avrdude: ser_open(): can't set attributes for device "/dev/ttyS0": Inappropriate ioctl for device
Looking further in that same forum, it appears the person having problems stated that you can’t power the chip you’re programming with the same Arduino that is programming it. Going to try an external power source for the chip before exploring the “inappropriate ioctl” error.
With externally powering the chip, I made some progress! In which this was:
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
This person linked to another post which covered that through USB, the arduino UNO doesn’t get enough power to read fuse bytes (very weird bug in the hardware apparently), so I’m going to try feeding the external GND and VCC into the arduino UNO as well.
That didn’t do anything, same error received.
Doing some more research, this problem could be a multitude of things:
I know the cord isn’t faulty, I can program other boot-loaded ATmegas with it. Nothing is connected to the RXD0 pin, so I can rule that out as well.
I know I never fuse-byte programmed it, so the only remaining option could be the bootloader.
I went about using OptiBoot to burn the bootloader on the ATmega328p, this could potentially be the problem. I have some empty ATMegas, so I’m going to attempt burning the regular bootloader on those to see if I can get any different response.
While getting it set up, I ran into the error of ‘missing ‘bootloader.tool’ configuration parameter. I found the solution here.
So I need to add the lines:
arduino328bb.bootloader.tool=arduino:avrdude
to boards.txt. After that, Things started to run! Almost.
I got the error of an incorrect file path, so it couldn’t read the hex file. hunts down file
incorrect file path: ~/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/hardware/arduino/avr/bootloaders/ATmegaBOOT_168_atmega328_pro_8MHz.hex
correct file path: ~/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/hardware/arduino/avr/bootloaders/atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
Instead of changing the path, I just moved the file to the directory it wanted.
Believe it or not, IT WORKED. WOOO.
Alright, this is great. One step closer to figuring this thing out.
With the newly bootloaded ATMega328p, I ran the command again:
avrdude -c arduino -p m328p -P /dev/ttyACM0 -b 19200 -U lfuse:r:-:h
which produced this error:
avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14
avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x01
avrdude: stk500_initialize(): (a) protocol error, expect=0x14, resp=0x10
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
avrdude: stk500_disable(): unknown response=0x12
I took out the “-b 19200” flag/value, and ran the command again, which returned:
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f
avrdude: Expected signature for ATmega328P is 1E 95 14
Double check chip, or use -F to override this check.
Apparently, people just suggested in this forum post to change the avrdude configuration to recognize my ATmega’s signature XD Seems legit. Lets try it. (https://www.avrfreaks.net/forum/difference-between-atmega328-328p-and-328pu?
whereis avrdude
told me that my avrdude configuration file was in /etc/avrdude.conf
So I sudo vimmed into it, and found the ATmega328P entry on line 8681. I changed the signature to be: 0x1e 0x95 0x0f
And that sort of worked! This was the output of that.
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading lfuse memory:
Reading | ################################################## | 100% 0.00s
avrdude: writing output file ""
0x0
avrdude: safemode: Fuses OK (E:00, H:00, L:00)
…I’m not entirely sure that the fuses should be ‘00’. In one forum post, they said part of the issue is avrdude using “safe mode”. To disable safe mode, I added a -u to the command:
avrdude -c arduino -p m328p -P /dev/ttyACM0 -v -u -U lfuse:r:-:h
Humm, that didn’t seem to do anything. The output file still reads “0x0”. I am not entirely sure this is a huge issue, though.
So I did some research and found this great site.
And it makes burning the fuses look really easy….so I’ma try it.
The fuses I need look like this:
L: 0x62
H: 0xD9
E: 0xFF
And he just adds an entry in “boards.txt” to take care of it. genius. Lets try this out…
#####################################################################
atmega328pbb.name=ATmega328P breadboard w/ internal 8MHz
atmega328pbb.upload.protocal=stk500
atmega328pbb.upload.maximum_size=32768
atmega328pbb.upload.speed=57600
atmega328pbb.upload.using=arduino:avrdude
atmega328pbb.bootloader.low_fuses=0x62
atmega328pbb.bootloader.high_fuses=0xd9
atmega328pbb.bootloader.extended_fuses=0xFF
atmega328pbb.bootloader.path=arduino:atmega
atmega328pbb.bootloader.file=ATmgeaBOOT_168_atmega328_pro_8MHz.hex
atmega328pbb.bootloader.unlock_bits=0x3F
atmega328pbb.bootloader.lock_bits=0x0F
atmega328pbb.build.mcu=atmega328p
atmega328pbb.build.f_cpu=8000000L
atmega328pbb.build.core=arduino:arduino
atmega.build.variant/arduino:standard
There’s my custom entry. Lets run it and see how that does.
The arduino UNO is still connected to my circuit, and still has the bootloader code on it. I got the same error as I did earlier:
Error while burning bootloader: missing ‘bootloader.tool’ configuration parameter
So I went back into boards.txt and changed this line:
atmega328pbb.upload.using=arduino:avrdude
to:
atmega328pbb.bootloader.tool=arduino:avrdude
restarted the ArduinoIDE, burned, and got this error:
avrdude: can't open input file /home/thallia/Downloads/arduino-1.8.5-linux64/arduino-1.8.5/hardware/arduino/avr/bootloaders/ATmgeaBOOT_168_atmega328_pro_8MHz.hex: No such file or directory
..which I should’ve fixed that…oh derp. “atmega” not “atmgea”. facepalm.
:oooo no errors!! woohoo! Okay, so the fuse bytes should have been changed with that. Let’s see what avrdude did:
avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0xFF"
avrdude: writing efuse (1 bytes):
Writing | ##############################################$
### | 100% 0.01s
avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFF:
avrdude: load data efuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip efuse data:
Reading | ##############################################$
### | 100% 0.01s
User configuration file is "/home/thallia/.avrd$
derc"
avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xd9"
avrdude: writing hfuse (1 bytes):
Writing | ##############################################$
### | 100% 0.01s
avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xd9:
avrdude: load data hfuse data from input file 0xd9:
avrdude: input file 0xd9 contains 1 bytes
avrdude: reading on-chip hfuse data:
Reading | ##############################################$
### | 100% 0.01s
avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0x62"
avrdude: writing lfuse (1 bytes):
Writing | ##############################################$
### | 100% 0.01s
avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0x62:
avrdude: load data lfuse data from input file 0x62:
avrdude: input file 0x62 contains 1 bytes
avrdude: reading on-chip lfuse data:
Reading | ###############################################
### | 100% 0.01s
avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude done. Thank you.
duuuuuude. how come I didn’t know it was this easy before?
lets test out the microcontroller now!
okay so looks like you actually have to have an “upload.tool” line in boards.txt or else it won’t let you upload a thing. After that, it still wouldn’t upload, giving me that annoying “programmer is not responding/not in sync” error.
After looking around on Nick Gammon’s site, if the “divide by 8” fuse bit is set, you can’t upload programs…so now I gotta fix that.
I went and changed the fuse byte from 0xD9 to 0xE2, which changes the CKDIV8 bit. When burning the bootloader though, it has an error.
avrdude: verification error, first mismatch at byte 0x0000
0xc2 != 0xe2
avrdude: verification error; content mismatch
I wonder why it’s writing c and not e. Lets try programming it and see what happens.
oh crud. I changed the high fuse not the low fuse. Back to the boards.txt…..
okay, that fixed it. Phew, I thought I may have bricked it there for a sec. Now lets try programming it again…
Oops, it looks like it’s not actually using the bootloader, so it can’t upload the program. That would make sense.
This time I need to change the High Fuse byte to 0xD8 instead of 0xD9. Testing program uploading again….. and boom. It worked. :D
turns out none of those were actually the errors lol, the UNO just needed its own atmega328p in it. derp
The test circuit worked, and it drew the expected amount of current. WOOOHOOOO. major progress!
Now I have a working microcontroller, working code (aside from the buttons), and a full on new schematic!
With this schematic (yes I know it’s ugly for now) I’ll generate the PCB, route the PCB, order some new parts, and then this project will be nearing its end.
Woo, that was a ton of work, but it totally paid off.
Happy hacking y’all!
{thallia}