Atmega328p 3.3V: Obtaining REPEATABLE end-to-end bootloader + programming

Ideal Setup:

  • 3.3V Atmega328p running as SLOW as possible (8Mhz currently)
  • NO external crystal - what's the point of having an internal oscillator if it's necessary to duplicate this with an external one? Don't care if we're off from 10% or if there's a little drift with temperature. Doesn't matter for this application.
  • Ideally, 1Mhz (or even slower if possible -- I don't have a good excuse for speed for this application); power consumption is king.
  • For software, just using the Arduino IDE frontend, but I'm not afraid to dig into the more esoteric aspects of avrdude, as I suspect will be required.
  • NO level shifters. These chips are relatively expensive and only used for programming. Better to have a design with just two rails end-to-end (3.3 and GND).
  • NO TXD/RXD interface. Plugging in ICSP header and "Upload using Programmer" is fine.

Goal:

  • Set up factory-new device with a bootloader and sketch given the hardware constrains set forth above.
  • Know how to tune the internal oscillator. According to this , from the factory the oscillator is calibrated to +/- 10%, but custom calibration can get us to within +/- 1%. Would that be good enough for repeatability if added before the "burn bootloader" step?

Discussion:

I would like to be able able to program with no/zero/nada 5VDC in the pipeline, which rules out any unmodified Arduino because it uses the venerable 5VDC. Even the high-end Due, which is a 3.3VDC device, insists on having 5VDC in the ICSP, so that's out as an option.

Reset line in current setup features a 10k pull-up resistor to 3.3VDC w/the 100pF cap to GND.

Had success programming from a 5VDC Uno to independently-powered 3.3VDC 328p devices, both through-hole and SMD. This appears to be repeatable. However, this is dangerous as the MOSI/MISO/SCK/RESET are still coming from 5VDC, and of course this drives the internal protection circuitry on the target and could eventually cause thermal damage - kinda like Russian Roulette each time it's reprogrammed and therefore not repeatable.

Bought an inexpensive USBasp from Amazon and set to 3.3VDC. Worked 5-6 times then the USBasp device itself failed, and no longer appears as a "port". An inspection of the board revealed poor build quality - it was not even cleaned prior to shipping. Have ordered another one which says it works for 3.3VDC applications; we shall see. It also took out a SMD 328p. An hour of unsoldering that and replacing it with another and going back to the proven but dangerous Uno programming method and I didn't even get as far as I was previously: Bootloader would "sort of" load, but with errors. My best guess is the first, now destroyed one, had the factory oscillator calibrated closer to a tolerable frequency for programming.

I'm unfamiliar with the data flow and handshaking -- should probably read up on that -- but it seems an ACK/NACK method would be superior. Don't really care about the speed of the upload (as long as it doesn't take hours), but I care a great deal about consistent, repeatable behavior.

gh42: * Ideally, 1Mhz (or even slower if possible -- I don't have a good excuse for speed for this application); power consumption is the concern.

Depending on what you're doing, a slow clock may not be helpful for reducing power consumption. In a situation where the microcontroller is only woken up when something needs to be done, then goes back to sleep immediately, a slower clock means it takes longer to accomplish that task, which negates the lower power consumption of running at a slower speed. If the microcontroller is hanging around awake doing nothing then a lower clock speed will certainly be helpful to lower the power consumption.

gh42: * For software, just using the Arduino IDE frontend, but I'm not afraid to dig into the more esoteric aspects of avrdude, as I suspect will be required.

MiniCore has 8 MHz and 1 MHz internal oscillator options: https://github.com/MCUdude/MiniCore

gh42: which rules out any unmodified Arduino because it uses the venerable 5VDC.

You can get 8 MHz, 3.3 V Pro Minis. But you'd want to remove the power indicator LED if you're concerned about power consumption, as well as the voltage regulator if you're not using it. I'd suspect some of the SAMD boards would meet your requirements but I haven't looked closely enough at any of them to be sure.

gh42: this is dangerous as the MOSI/MISO/SCK/RESET are still coming from 5VDC, and of course this drives the internal protection circuitry on the target and could eventually cause thermal damage - kinda like Russian Roulette each time it's reprogrammed and therefore not repeatable.

It all depends on the other components in the circuit. There's no problem with programming the ATmega328P with 5 V logic levels as long as you're also powering it at 5 V during the programming. The problem comes if other parts of the circuit would be damaged by being powered at 5 V during the programming.

gh42: Bought an inexpensive USBasp from Amazon and set to 3.3VDC. Worked 5-6 times then the USBasp device itself failed

Bad luck. I've been using exclusively the absolute cheapest USBasps (multiple styles) from eBay for years and have never had a problem with any of them.

gh42: and no longer appears as a "port".

USBasp never appears as a port. It's a USB device.

gh42: it was not even cleaned prior to shipping.

I noticed quite a bit of flux residue on all of my blue 10 pin USBasps with the adjustable voltage. The 6 pin ones I favor are cleaner.

Thank you for the clarifications.

I have my own PCB design for the SMD 328p. Can program.

Good point re: running slower may not reduce power consumption. This particular firmware does run off an interrupt, "wakes up", reads sensors over SPI, does a few calculations, prints numbers and a graph to an LCD display, then goes back to sleep. It does this approx. 4 times a second (4Hz). It also reads user input, also interrupt driven, from a few push buttons. 8Mhz would likely be fine.

Trying another USBasp type device. The one that seemingly turned bad appeared to have a very thin strand of copper wire between one of the crystal pins and an adjacent SMD component.

Wish I could remember if it appeared as a "port" - I thought it did, but maybe not...

MiniCore is solid. I've been very impressed with this library - even supports the new "PB" devices.

gh42: the USBasp device itself failed, and no longer appears as a "port".

Are you getting a "Please select a Port before Upload" error? There was a bug introduced with a new feature in Arduino IDE 1.8.7 that causes this error when trying to do an Upload Using Programmer when the Arduino IDE's stored previous port property in preferences.txt indicates that you have never selected a port: https://github.com/arduino/Arduino/issues/8052

Running 1.8.5 - will stay away from 1.8.7 for the time being thanks to your information.

It looks like the USBasp does work after all: Moving backwards, tried it using a breadboard-connected 328p and it appears to work fine.

I'm making some modifications to my design now and learning about fine-tuning the internal oscillator. That's probably one of the secret sauces for predictable behavior from device to device... It will be great to hammer this out for everyone and make the external oscillator purely voluntary...

Thanks everyone - I'm both grateful and impressed by your responses!

The workaround for that bug is simple so I wouldn't let it hold you back from using the otherwise excellent Arduino IDE 1.8.7. You only need to select a port from the Tools > Port menu once. It doesn't matter what the port is. The feature is intended to help with the very common problem new users have where they install the IDE, open a sketch, plug in their Arduino board, and hit the "Upload" button, neglecting to read the instructions about needing to select their board's port from the Tools > Port menu. Previously, this would result in a somewhat cryptic error like:

avrdude: ser_open(): can't open device "\\.\COM1": The system cannot find the file specified.

So this gives a somewhat more helpful error message. Unfortunately, they didn't account for the fact that when you are using a USB ISP programmer to upload to your Arduino (which some boards like the Adafruit Trinket have built in), you don't need to select a port.

I thought there might be a chance that bug had made you think the USBasps were broken. I'm glad to hear they're working for you again. I'm a really big fan of the USBasp. I own all the other common programmers, including a relatively expensive (and now rare) Atmel AVRISP mkII, but only ever use my cheapo USBasp.

Arduino IDE 1.8.5 had a few bugs. The one that most bothered me was the ridiculously slow startup time. There is also a problem with Windows OneDrive but I don't use that so it didn't affect me.

Considering your ideal setup and goal, you don't need to program a bootloader at all. Just use a programmer and avrdude to set the fuses, and upload your program using the IDE or with avrdude. Bootloaders are for when you want to use serial to upload, so if you are uploading via ICSP you don't need one.

You may not gain any power savings when the MCU is awake for longer periods of time running at lower speed. You may be better off with short time the MCU is awake running at 8MHz rather than having it awake and using more power for 8 times longer running at 1MHz. Do some experiments to see what you get. Set fuses to run it at 8MHz or 1MHz using the divide by 8 fuse.

You can use any 5V programmer, including an Arduino as ISP, and program at 3.3V with a very inexpensive level converter like this one https://www.sparkfun.com/products/12009 There are clones of it on sites like Aliexpress for 65 cents postage included. Sounds like you may already have it figured out with the USBasp, but you do have options.

I've gotten my Revision C boards back from fabrication. It now features a 30A SMD fuse (relevant to my application, which involves a high load) and a jumper to connect/disconned the 3.3VDC onboard supply, useful if one wants to connect an ICSP directly with supply power (won't take out the onboard regulator).

Good news: I believe the problem was a mis-valued decoupler cap: it was only 100pF and should have been 100nF (0.1uF), so off by three orders of magnitude... Actually I used a 0.47uF ceramic cap, 0402 package.

With this fix, I was able to program the bootloader and code on the first try, and by a happy mistake the bootloader burned the fuses for 1Mhz operation, which is really what I wanted all along. This is the first time I've been able to operate it at that speed.

I have 3.3VDC end-to-end, no level converters, and running at 1Mhz.

Moral of the story: that decoupling capacitor is really important. Now back to development!

I'm glad to hear you found the solution. The decoupling capacitors are indeed important. Enjoy! Per